home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Applications / P4⁄Mac 2.0d4 / Original source & doc / pcom.p < prev    next >
Encoding:
Text File  |  1994-07-28  |  114.9 KB  |  4,001 lines  |  [TEXT/ttxt]

  1. (*$c+,t-,d-,l-*)
  2.  (***********************************************
  3.   *                        *
  4.   *     Portable Pascal compiler        *
  5.   *     ************************        *
  6.   *                        *
  7.   *        Pascal P4            *
  8.   *                        *
  9.   *     Authors:                *
  10.   *          Urs Ammann            *
  11.   *          Kesav Nori            *
  12.   *          Christian Jacobi            *
  13.   *     Address:                *
  14.   *      Institut Fuer Informatik        *
  15.   *      Eidg. Technische Hochschule        *
  16.   *      CH-8096 Zuerich            *
  17.   *                        *
  18.   *  This code is fully documented in the book    *
  19.   *       "Pascal Implementation"        *
  20.   *   by Steven Pemberton and Martin Daniels    *
  21.   * published by Ellis Horwood, Chichester, UK    *
  22.   *        ISBN: 0-13-653-0311            *
  23.   *       (also available in Japanese)        *
  24.   *                        *
  25.   * Steven Pemberton, CWI/AA,            *
  26.   * Kruislaan 413, 1098 SJ Amsterdam, NL    *
  27.   * Steven.Pemberton@cwi.nl            *
  28.   *                        *
  29.   ***********************************************)
  30.  
  31. program pascalcompiler(input,output,prr);
  32.  
  33. const displimit = 20; maxlevel = 10;
  34.    intsize     =      1;
  35.    intal       =      1;
  36.    realsize    =      1;
  37.    realal      =      1;
  38.    charsize    =      1;
  39.    charal      =      1;
  40.    charmax     =      1;
  41.    boolsize    =      1;
  42.    boolal      =      1;
  43.    ptrsize     =      1;
  44.    adral       =      1;
  45.    setsize     =      1;
  46.    setal       =      1;
  47.    stackal     =      1;
  48.    stackelsize =      1;
  49.    strglgth    =     16;
  50.    sethigh     =     47;
  51.    setlow      =      0;
  52.    ordmaxchar  =     63;
  53.    ordminchar  =      0;
  54.    maxint      =  32767;
  55.    lcaftermarkstack = 5;
  56.    fileal      = charal;
  57.    (* stackelsize = minimum size for 1 stackelement
  58.           = k*stackal
  59.       stackal     = scm(all other al-constants)
  60.       charmax     = scm(charsize,charal)
  61.             scm = smallest common multiple
  62.       lcaftermarkstack >= 4*ptrsize+max(x-size)
  63.             = k1*stackelsize      *)
  64.    maxstack   =       1;
  65.    parmal     = stackal;
  66.    parmsize   = stackelsize;
  67.    recal      = stackal;
  68.    filebuffer =       4;
  69.    maxaddr    =  maxint;
  70.  
  71.  
  72.  
  73. type                            (*describing:*)
  74.                                 (*************)
  75.  
  76.      marktype= ^integer;
  77.                                 (*basic symbols*)
  78.                                 (***************)
  79.  
  80.      symbol = (ident,intconst,realconst,stringconst,notsy,mulop,addop,relop,
  81.            lparent,rparent,lbrack,rbrack,comma,semicolon,period,arrow,
  82.            colon,becomes,labelsy,constsy,typesy,varsy,funcsy,progsy,
  83.            procsy,setsy,packedsy,arraysy,recordsy,filesy,forwardsy,
  84.            beginsy,ifsy,casesy,repeatsy,whilesy,forsy,withsy,
  85.            gotosy,endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy,
  86.            thensy,othersy);
  87.      operator = (mul,rdiv,andop,idiv,imod,plus,minus,orop,ltop,leop,geop,gtop,
  88.          neop,eqop,inop,noop);
  89.      setofsys = set of symbol;
  90.      chtp = (letter,number,special,illegal,
  91.          chstrquo,chcolon,chperiod,chlt,chgt,chlparen,chspace);
  92.  
  93.                                 (*constants*)
  94.                                 (***********)
  95.      setty = set of setlow..sethigh;
  96.      cstclass = (reel,pset,strg);
  97.      csp = ^ constant;
  98.      constant = record case cclass: cstclass of
  99.              reel: (rval: packed array [1..strglgth] of char);
  100.              pset: (pval: setty);
  101.              strg: (slgth: 0..strglgth;
  102.                 sval: packed array [1..strglgth] of char)
  103.                end;
  104.  
  105.      valu = record case intval: boolean of  (*intval never set nor tested*)
  106.              true:  (ival: integer);
  107.              false: (valp: csp)
  108.            end;
  109.  
  110.                                (*data structures*)
  111.                                (*****************)
  112.      levrange = 0..maxlevel; addrrange = 0..maxaddr;
  113.      structform = (scalar,subrange,pointer,power,arrays,records,files,
  114.            tagfld,variant);
  115.      declkind = (standard,declared);
  116.      stp = ^ structure; ctp = ^ identifier;
  117.  
  118.      structure = packed record
  119.            marked: boolean;   (*for test phase only*)
  120.            size: addrrange;
  121.            case form: structform of
  122.              scalar:   (case scalkind: declkind of
  123.                   declared: (fconst: ctp); standard: ());
  124.              subrange: (rangetype: stp; min,max: valu);
  125.              pointer:  (eltype: stp);
  126.              power:    (elset: stp);
  127.              arrays:   (aeltype,inxtype: stp);
  128.              records:  (fstfld: ctp; recvar: stp);
  129.              files:    (filtype: stp);
  130.              tagfld:   (tagfieldp: ctp; fstvar: stp);
  131.              variant:  (nxtvar,subvar: stp; varval: valu)
  132.            end;
  133.  
  134.                                 (*names*)
  135.                                 (*******)
  136.  
  137.      idclass = (types,konst,vars,field,proc,func);
  138.      setofids = set of idclass;
  139.      idkind = (actual,formal);
  140.      alpha = packed array [1..8] of char;
  141.  
  142.      identifier = packed record
  143.            name: alpha; llink, rlink: ctp;
  144.            idtype: stp; next: ctp;
  145.            case klass: idclass of
  146.              types: ();
  147.              konst: (values: valu);
  148.              vars:  (vkind: idkind; vlev: levrange; vaddr: addrrange);
  149.              field: (fldaddr: addrrange);
  150.              proc, func:  (case pfdeckind: declkind of
  151.                   standard: (key: 1..15);
  152.                   declared: (pflev: levrange; pfname: integer;
  153.                       case pfkind: idkind of
  154.                        actual: (forwdecl, externl: boolean);
  155.                        formal: ()))
  156.            end;
  157.  
  158.  
  159.      disprange = 0..displimit;
  160.      where = (blck,crec,vrec,rec);
  161.  
  162.                                 (*expressions*)
  163.                                 (*************)
  164.      attrkind = (cst,varbl,expr);
  165.      vaccess = (drct,indrct,inxd);
  166.  
  167.      attr = record typtr: stp;
  168.           case kind: attrkind of
  169.         cst:   (cval: valu);
  170.         varbl: (case access: vaccess of
  171.               drct: (vlevel: levrange; dplmt: addrrange);
  172.               indrct: (idplmt: addrrange))
  173.           end;
  174.  
  175.      testp = ^ testpointer;
  176.      testpointer = packed record
  177.              elt1,elt2 : stp;
  178.              lasttestp : testp
  179.            end;
  180.  
  181.                                  (*labels*)
  182.                                  (********)
  183.      lbp = ^ labl;
  184.      labl = record nextlab: lbp; defined: boolean;
  185.            labval, labname: integer
  186.         end;
  187.  
  188.      extfilep = ^filerec;
  189.      filerec = record filename:alpha; nextfile:extfilep end;
  190.  
  191. (*-------------------------------------------------------------------------*)
  192.  
  193. var
  194.     prr: text; (* comment this out when compiling with pcom *)
  195.                     (*returned by source program scanner
  196.                      insymbol:
  197.                      **********)
  198.  
  199.     sy: symbol;             (*last symbol*)
  200.     op: operator;           (*classification of last symbol*)
  201.     val: valu;              (*value of last constant*)
  202.     lgth: integer;          (*length of last string constant*)
  203.     id: alpha;              (*last identifier (possibly truncated)*)
  204.     kk: 1..8;               (*nr of chars in last identifier*)
  205.     ch: char;               (*last character*)
  206.     eol: boolean;           (*end of line flag*)
  207.  
  208.  
  209.                     (*counters:*)
  210.                     (***********)
  211.  
  212.     chcnt: integer;         (*character counter*)
  213.     lc,ic: addrrange;           (*data location and instruction counter*)
  214.     linecount: integer;
  215.  
  216.  
  217.                     (*switches:*)
  218.                     (***********)
  219.  
  220.     dp,                 (*declaration part*)
  221.     prterr,             (*to allow forward references in pointer type
  222.                       declaration by suppressing error message*)
  223.     list,prcode,prtables: boolean;  (*output options for
  224.                     -- source program listing
  225.                     -- printing symbolic code
  226.                     -- displaying ident and struct tables
  227.                     --> procedure option*)
  228.     debug: boolean;
  229.  
  230.  
  231.                     (*pointers:*)
  232.                     (***********)
  233.     parmptr,
  234.     intptr,realptr,charptr,
  235.     boolptr,nilptr,textptr: stp;    (*pointers to entries of standard ids*)
  236.     utypptr,ucstptr,uvarptr,
  237.     ufldptr,uprcptr,ufctptr,    (*pointers to entries for undeclared ids*)
  238.     fwptr: ctp;             (*head of chain of forw decl type ids*)
  239.     fextfilep: extfilep;        (*head of chain of external files*)
  240.     globtestp: testp;           (*last testpointer*)
  241.  
  242.  
  243.                     (*bookkeeping of declaration levels:*)
  244.                     (************************************)
  245.  
  246.     level: levrange;        (*current static level*)
  247.     disx,               (*level of last id searched by searchid*)
  248.     top: disprange;         (*top of display*)
  249.  
  250.     display:            (*where:   means:*)
  251.       array [disprange] of
  252.     packed record           (*=blck:   id is variable id*)
  253.       fname: ctp; flabel: lbp;  (*=crec:   id is field id in record with*)
  254.       case occur: where of      (*     constant address*)
  255.         crec: (clev: levrange;  (*=vrec:   id is field id in record with*)
  256.           cdspl: addrrange);(*     variable address*)
  257.         vrec: (vdspl: addrrange)
  258.       end;              (* --> procedure withstatement*)
  259.  
  260.  
  261.                     (*error messages:*)
  262.                     (*****************)
  263.  
  264.     errinx: 0..10;          (*nr of errors in current source line*)
  265.     errlist:
  266.       array [1..10] of
  267.     packed record pos: integer;
  268.               nmr: 1..400
  269.            end;
  270.  
  271.  
  272.  
  273.                     (*expression compilation:*)
  274.                     (*************************)
  275.  
  276.     gattr: attr;            (*describes the expr currently compiled*)
  277.  
  278.  
  279.                     (*structured constants:*)
  280.                     (***********************)
  281.  
  282.     constbegsys,simptypebegsys,typebegsys,blockbegsys,selectsys,facbegsys,
  283.     statbegsys,typedels: setofsys;
  284.     chartp : array[char] of chtp;
  285.     rw:  array [1..35(*nr. of res. words*)] of alpha;
  286.     frw: array [1..9] of 1..36(*nr. of res. words + 1*);
  287.     rsy: array [1..35(*nr. of res. words*)] of symbol;
  288.     ssy: array [char] of symbol;
  289.     rop: array [1..35(*nr. of res. words*)] of operator;
  290.     sop: array [char] of operator;
  291.     na:  array [1..35] of alpha;
  292.     mn:  array [0..60] of packed array [1..4] of char;
  293.     sna: array [1..23] of packed array [1..4] of char;
  294.     cdx: array [0..60] of -4..+4;
  295.     pdx: array [1..23] of -7..+7;
  296.     ordint: array [char] of integer;
  297.  
  298.     intlabel,mxint10,digmax: integer;
  299. (*-------------------------------------------------------------------------*)
  300.   procedure mark(var p: marktype); begin end;
  301.   procedure release(p: marktype); begin end;
  302.  
  303.   procedure endofline;
  304.     var lastpos,freepos,currpos,currnmr,f,k: integer;
  305.   begin
  306.     if errinx > 0 then   (*output error messages*)
  307.       begin write(output,linecount:6,' ****  ':9);
  308.     lastpos := 0; freepos := 1;
  309.     for k := 1 to errinx do
  310.       begin
  311.         with errlist[k] do
  312.           begin currpos := pos; currnmr := nmr end;
  313.         if currpos = lastpos then write(output,',')
  314.         else
  315.           begin
  316.         while freepos < currpos do
  317.           begin write(output,' '); freepos := freepos + 1 end;
  318.         write(output,'^');
  319.         lastpos := currpos
  320.           end;
  321.         if currnmr < 10 then f := 1
  322.         else if currnmr < 100 then f := 2
  323.           else f := 3;
  324.         write(output,currnmr:f);
  325.         freepos := freepos + f + 1
  326.       end;
  327.     writeln(output); errinx := 0
  328.       end;
  329.     linecount := linecount + 1;
  330.     if list and (not eof(input)) then
  331.       begin write(output,linecount:6,'  ':2);
  332.     if dp then write(output,lc:7) else write(output,ic:7);
  333.     write(output,' ')
  334.       end;
  335.     chcnt := 0
  336.   end  (*endofline*) ;
  337.  
  338.   procedure error(ferrnr: integer);
  339.   begin
  340.     if errinx >= 9 then
  341.       begin errlist[10].nmr := 255; errinx := 10 end
  342.     else
  343.       begin errinx := errinx + 1;
  344.     errlist[errinx].nmr := ferrnr
  345.       end;
  346.     errlist[errinx].pos := chcnt
  347.   end (*error*) ;
  348.  
  349.   procedure insymbol;
  350.     (*read next basic symbol of source program and return its
  351.     description in the global variables sy, op, id, val and lgth*)
  352.     label 1,2,3;
  353.     var i,k: integer;
  354.     digit: packed array [1..strglgth] of char;
  355.     string: packed array [1..strglgth] of char;
  356.     lvp: csp; test: boolean;
  357.  
  358.     procedure nextch;
  359.     begin if eol then
  360.       begin if list then writeln(output); endofline
  361.       end;
  362.       if not eof(input) then
  363.        begin eol := eoln(input); read(input,ch);
  364.     if list then write(output,ch);
  365.     chcnt := chcnt + 1
  366.        end
  367.       else
  368.     begin writeln(output,'   *** eof ','encountered');
  369.       test := false
  370.     end
  371.     end;
  372.  
  373.     procedure options;
  374.     begin
  375.       repeat nextch;
  376.     if ch <> '*' then
  377.       begin
  378.         if ch = 't' then
  379.           begin nextch; prtables := ch = '+' end
  380.         else
  381.           if ch = 'l' then
  382.         begin nextch; list := ch = '+';
  383.           if not list then writeln(output)
  384.         end
  385.           else
  386.          if ch = 'd' then
  387.            begin nextch; debug := ch = '+' end
  388.          else
  389.         if ch = 'c' then
  390.           begin nextch; prcode := ch = '+' end;
  391.         nextch
  392.       end
  393.       until ch <> ','
  394.     end (*options*) ;
  395.  
  396.   begin (*insymbol*)
  397.   1:
  398.     repeat while ((ch = ' ') or (ch = '    ')) and not eol do nextch;
  399.       test := eol;
  400.       if test then nextch
  401.     until not test;
  402.     if chartp[ch] = illegal then
  403.       begin sy := othersy; op := noop;
  404.     error(399); nextch
  405.       end
  406.     else
  407.     case chartp[ch] of
  408.       letter:
  409.     begin k := 0;
  410.       repeat
  411.         if k < 8 then
  412.          begin k := k + 1; id[k] := ch end ;
  413.         nextch
  414.       until chartp[ch] in [special,illegal,chstrquo,chcolon,
  415.                 chperiod,chlt,chgt,chlparen,chspace];
  416.       if k >= kk then kk := k
  417.       else
  418.         repeat id[kk] := ' '; kk := kk - 1
  419.         until kk = k;
  420.       for i := frw[k] to frw[k+1] - 1 do
  421.         if rw[i] = id then
  422.           begin sy := rsy[i]; op := rop[i]; goto 2 end;
  423.         sy := ident; op := noop;
  424.   2:    end;
  425.       number:
  426.     begin op := noop; i := 0;
  427.       repeat i := i+1; if i<= digmax then digit[i] := ch; nextch
  428.       until chartp[ch] <> number;
  429.       if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then
  430.         begin
  431.           k := i;
  432.           if ch = '.' then
  433.             begin k := k+1; if k <= digmax then digit[k] := ch;
  434.               nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*)
  435.               if chartp[ch] <> number then error(201)
  436.               else
  437.             repeat k := k + 1;
  438.               if k <= digmax then digit[k] := ch; nextch
  439.             until chartp[ch] <>  number
  440.             end;
  441.           if ch = 'e' then
  442.             begin k := k+1; if k <= digmax then digit[k] := ch;
  443.               nextch;
  444.               if (ch = '+') or (ch ='-') then
  445.             begin k := k+1; if k <= digmax then digit[k] := ch;
  446.               nextch
  447.             end;
  448.               if chartp[ch] <> number then error(201)
  449.               else
  450.             repeat k := k+1;
  451.               if k <= digmax then digit[k] := ch; nextch
  452.             until chartp[ch] <> number
  453.              end;
  454.            new(lvp,reel); sy:= realconst; lvp^.cclass := reel;
  455.            with lvp^ do
  456.              begin for i := 1 to strglgth do rval[i] := ' ';
  457.                if k <= digmax then
  458.              for i := 2 to k + 1 do rval[i] := digit[i-1]
  459.                else begin error(203); rval[2] := '0';
  460.                   rval[3] := '.'; rval[4] := '0'
  461.                 end
  462.              end;
  463.            val.valp := lvp
  464.         end
  465.       else
  466.   3:    begin
  467.           if i > digmax then begin error(203); val.ival := 0 end
  468.           else
  469.         with val do
  470.           begin ival := 0;
  471.             for k := 1 to i do
  472.               begin
  473.             if ival <= mxint10 then
  474.               ival := ival*10+ordint[digit[k]]
  475.             else begin error(203); ival := 0 end
  476.               end;
  477.             sy := intconst
  478.           end
  479.         end
  480.     end;
  481.       chstrquo:
  482.     begin lgth := 0; sy := stringconst;  op := noop;
  483.       repeat
  484.         repeat nextch; lgth := lgth + 1;
  485.            if lgth <= strglgth then string[lgth] := ch
  486.         until (eol) or (ch = '''');
  487.         if eol then error(202) else nextch
  488.       until ch <> '''';
  489.       lgth := lgth - 1;   (*now lgth = nr of chars in string*)
  490.       if lgth = 0 then error(205) else
  491.       if lgth = 1 then val.ival := ord(string[1])
  492.       else
  493.         begin new(lvp,strg); lvp^.cclass:=strg;
  494.           if lgth > strglgth then
  495.         begin error(399); lgth := strglgth end;
  496.           with lvp^ do
  497.         begin slgth := lgth;
  498.           for i := 1 to lgth do sval[i] := string[i]
  499.         end;
  500.           val.valp := lvp
  501.         end
  502.     end;
  503.       chcolon:
  504.     begin op := noop; nextch;
  505.       if ch = '=' then
  506.         begin sy := becomes; nextch end
  507.       else sy := colon
  508.     end;
  509.       chperiod:
  510.     begin op := noop; nextch;
  511.       if ch = '.' then
  512.         begin sy := colon; nextch end
  513.       else sy := period
  514.     end;
  515.       chlt:
  516.     begin nextch; sy := relop;
  517.       if ch = '=' then
  518.         begin op := leop; nextch end
  519.       else
  520.         if ch = '>' then
  521.           begin op := neop; nextch end
  522.         else op := ltop
  523.     end;
  524.       chgt:
  525.     begin nextch; sy := relop;
  526.       if ch = '=' then
  527.         begin op := geop; nextch end
  528.       else op := gtop
  529.     end;
  530.       chlparen:
  531.        begin nextch;
  532.      if ch = '*' then
  533.        begin nextch;
  534.          if ch = '$' then options;
  535.          repeat
  536.            while (ch <> '*') and not eof(input) do nextch;
  537.            nextch
  538.          until (ch = ')') or eof(input);
  539.          nextch; goto 1
  540.        end;
  541.      sy := lparent; op := noop
  542.        end;
  543.       special:
  544.     begin sy := ssy[ch]; op := sop[ch];
  545.       nextch
  546.     end;
  547.       chspace: sy := othersy
  548.     end (*case*)
  549.   end (*insymbol*) ;
  550.  
  551.   procedure enterid(fcp: ctp);
  552.     (*enter id pointed at by fcp into the name-table,
  553.      which on each declaration level is organised as
  554.      an unbalanced binary tree*)
  555.     var nam: alpha; lcp, lcp1: ctp; lleft: boolean;
  556.   begin nam := fcp^.name;
  557.     lcp := display[top].fname;
  558.     if lcp = nil then
  559.       display[top].fname := fcp
  560.     else
  561.       begin
  562.     repeat lcp1 := lcp;
  563.       if lcp^.name = nam then   (*name conflict, follow right link*)
  564.         begin error(101); lcp := lcp^.rlink; lleft := false end
  565.       else
  566.         if lcp^.name < nam then
  567.           begin lcp := lcp^.rlink; lleft := false end
  568.         else begin lcp := lcp^.llink; lleft := true end
  569.     until lcp = nil;
  570.     if lleft then lcp1^.llink := fcp else lcp1^.rlink := fcp
  571.       end;
  572.     fcp^.llink := nil; fcp^.rlink := nil
  573.   end (*enterid*) ;
  574.  
  575.   procedure searchsection(fcp: ctp; var fcp1: ctp);
  576.     (*to find record fields and forward declared procedure id's
  577.      --> procedure proceduredeclaration
  578.      --> procedure selector*)
  579.      label 1;
  580.   begin
  581.     while fcp <> nil do
  582.       if fcp^.name = id then goto 1
  583.       else if fcp^.name < id then fcp := fcp^.rlink
  584.     else fcp := fcp^.llink;
  585. 1:  fcp1 := fcp
  586.   end (*searchsection*) ;
  587.  
  588.   procedure searchid(fidcls: setofids; var fcp: ctp);
  589.     label 1;
  590.     var lcp: ctp;
  591.   begin
  592.     for disx := top downto 0 do
  593.       begin lcp := display[disx].fname;
  594.     while lcp <> nil do
  595.       if lcp^.name = id then
  596.         if lcp^.klass in fidcls then goto 1
  597.         else
  598.           begin if prterr then error(103);
  599.         lcp := lcp^.rlink
  600.           end
  601.       else
  602.         if lcp^.name < id then
  603.           lcp := lcp^.rlink
  604.         else lcp := lcp^.llink
  605.       end;
  606.     (*search not successful; suppress error message in case
  607.      of forward referenced type id in pointer type definition
  608.      --> procedure simpletype*)
  609.     if prterr then
  610.       begin error(104);
  611.     (*to avoid returning nil, reference an entry
  612.      for an undeclared id of appropriate class
  613.      --> procedure enterundecl*)
  614.     if types in fidcls then lcp := utypptr
  615.     else
  616.       if vars in fidcls then lcp := uvarptr
  617.       else
  618.         if field in fidcls then lcp := ufldptr
  619.         else
  620.           if konst in fidcls then lcp := ucstptr
  621.           else
  622.         if proc in fidcls then lcp := uprcptr
  623.         else lcp := ufctptr;
  624.       end;
  625. 1:  fcp := lcp
  626.   end (*searchid*) ;
  627.  
  628.   procedure getbounds(fsp: stp; var fmin,fmax: integer);
  629.     (*get internal bounds of subrange or scalar type*)
  630.     (*assume fsp<>intptr and fsp<>realptr*)
  631.   begin
  632.     fmin := 0; fmax := 0;
  633.     if fsp <> nil then
  634.     with fsp^ do
  635.       if form = subrange then
  636.     begin fmin := min.ival; fmax := max.ival end
  637.       else
  638.       if fsp = charptr then
  639.         begin fmin := ordminchar; fmax := ordmaxchar
  640.         end
  641.       else
  642.         if fconst <> nil then
  643.           fmax := fconst^.values.ival
  644.   end (*getbounds*) ;
  645.  
  646.   function alignquot(fsp: stp): integer;
  647.   begin
  648.     alignquot := 1;
  649.     if fsp <> nil then
  650.       with fsp^ do
  651.     case form of
  652.       scalar:   if fsp=intptr then alignquot := intal
  653.             else if fsp=boolptr then alignquot := boolal
  654.             else if scalkind=declared then alignquot := intal
  655.             else if fsp=charptr then alignquot := charal
  656.             else if fsp=realptr then alignquot := realal
  657.             else (*parmptr*) alignquot := parmal;
  658.       subrange: alignquot := alignquot(rangetype);
  659.       pointer:  alignquot := adral;
  660.       power:    alignquot := setal;
  661.       files:    alignquot := fileal;
  662.       arrays:   alignquot := alignquot(aeltype);
  663.       records:  alignquot := recal;
  664.       variant,tagfld: error(501)
  665.     end
  666.   end (*alignquot*);
  667.  
  668.   procedure align(fsp: stp; var flc: addrrange);
  669.     var k,l: integer;
  670.   begin
  671.     k := alignquot(fsp);
  672.     l := flc-1;
  673.     flc := l + k  -  (k+l) mod k
  674.   end (*align*);
  675.  
  676.   procedure printtables(fb: boolean);
  677.     (*print data structure and name table*)
  678.     var i, lim: disprange;
  679.  
  680.     procedure marker;
  681.       (*mark data structure entries to avoid multiple printout*)
  682.       var i: integer;
  683.  
  684.       procedure markctp(fp: ctp); forward;
  685.  
  686.       procedure markstp(fp: stp);
  687.     (*mark data structures, prevent cycles*)
  688.       begin
  689.     if fp <> nil then
  690.       with fp^ do
  691.         begin marked := true;
  692.           case form of
  693.           scalar:   ;
  694.           subrange: markstp(rangetype);
  695.           pointer:  (*don't mark eltype: cycle possible; will be marked
  696.             anyway, if fp = true*) ;
  697.           power:    markstp(elset) ;
  698.           arrays:   begin markstp(aeltype); markstp(inxtype) end;
  699.           records:  begin markctp(fstfld); markstp(recvar) end;
  700.           files:    markstp(filtype);
  701.           tagfld:   markstp(fstvar);
  702.           variant:  begin markstp(nxtvar); markstp(subvar) end
  703.           end (*case*)
  704.         end (*with*)
  705.       end (*markstp*);
  706.  
  707.       procedure markctp;
  708.       begin
  709.     if fp <> nil then
  710.       with fp^ do
  711.         begin markctp(llink); markctp(rlink);
  712.           markstp(idtype)
  713.         end
  714.       end (*markctp*);
  715.  
  716.     begin (*marker*)
  717.       for i := top downto lim do
  718.     markctp(display[i].fname)
  719.     end (*marker*);
  720.  
  721.     procedure followctp(fp: ctp); forward;
  722.  
  723.     procedure followstp(fp: stp);
  724.     begin
  725.       if fp <> nil then
  726.     with fp^ do
  727.       if marked then
  728.         begin marked := false; write(output,' ':4,ord(fp):6,size:10);
  729.           case form of
  730.           scalar:   begin write(output,'scalar':10);
  731.               if scalkind = standard then
  732.                 write(output,'standard':10)
  733.               else write(output,'declared':10,' ':4,ord(fconst):6);
  734.               writeln(output)
  735.             end;
  736.           subrange: begin
  737.               write(output,'subrange':10,' ':4,ord(rangetype):6);
  738.               if rangetype <> realptr then
  739.                 write(output,min.ival,max.ival)
  740.               else
  741.                 if (min.valp <> nil) and (max.valp <> nil) then
  742.                   write(output,' ',min.valp^.rval:9,
  743.                     ' ',max.valp^.rval:9);
  744.               writeln(output); followstp(rangetype);
  745.             end;
  746.           pointer:  writeln(output,'pointer':10,' ':4,ord(eltype):6);
  747.           power:    begin writeln(output,'set':10,' ':4,ord(elset):6);
  748.               followstp(elset)
  749.             end;
  750.           arrays:   begin
  751.               writeln(output,'array':10,' ':4,ord(aeltype):6,' ':4,
  752.                 ord(inxtype):6);
  753.               followstp(aeltype); followstp(inxtype)
  754.             end;
  755.           records:  begin
  756.               writeln(output,'record':10,' ':4,ord(fstfld):6,' ':4,
  757.                 ord(recvar):6); followctp(fstfld);
  758.               followstp(recvar)
  759.             end;
  760.           files:    begin write(output,'file':10,' ':4,ord(filtype):6);
  761.               followstp(filtype)
  762.             end;
  763.           tagfld:   begin writeln(output,'tagfld':10,' ':4,ord(tagfieldp):6,
  764.                 ' ':4,ord(fstvar):6);
  765.               followstp(fstvar)
  766.             end;
  767.           variant:  begin writeln(output,'variant':10,' ':4,ord(nxtvar):6,
  768.                 ' ':4,ord(subvar):6,varval.ival);
  769.               followstp(nxtvar); followstp(subvar)
  770.             end
  771.           end (*case*)
  772.         end (*if marked*)
  773.     end (*followstp*);
  774.  
  775.     procedure followctp;
  776.       var i: integer;
  777.     begin
  778.       if fp <> nil then
  779.     with fp^ do
  780.       begin write(output,' ':4,ord(fp):6,' ',name:9,' ':4,ord(llink):6,
  781.         ' ':4,ord(rlink):6,' ':4,ord(idtype):6);
  782.         case klass of
  783.           types: write(output,'type':10);
  784.           konst: begin write(output,'constant':10,' ':4,ord(next):6);
  785.                if idtype <> nil then
  786.              if idtype = realptr then
  787.                begin
  788.                  if values.valp <> nil then
  789.                    write(output,' ',values.valp^.rval:9)
  790.                end
  791.              else
  792.                if idtype^.form = arrays then  (*stringconst*)
  793.                  begin
  794.                    if values.valp <> nil then
  795.                  begin write(output,' ');
  796.                    with values.valp^ do
  797.                      for i := 1 to slgth do
  798.                        write(output,sval[i])
  799.                  end
  800.                  end
  801.                else write(output,values.ival)
  802.              end;
  803.           vars:  begin write(output,'variable':10);
  804.                if vkind = actual then write(output,'actual':10)
  805.                else write(output,'formal':10);
  806.                write(output,' ':4,ord(next):6,vlev,' ':4,vaddr:6 );
  807.              end;
  808.           field: write(output,'field':10,' ':4,ord(next):6,' ':4,fldaddr:6);
  809.           proc,
  810.           func:  begin
  811.                if klass = proc then write(output,'procedure':10)
  812.                else write(output,'function':10);
  813.                if pfdeckind = standard then
  814.              write(output,'standard':10, key:10)
  815.                else
  816.              begin write(output,'declared':10,' ':4,ord(next):6);
  817.                write(output,pflev,' ':4,pfname:6);
  818.                if pfkind = actual then
  819.                  begin write(output,'actual':10);
  820.                    if forwdecl then write(output,'forward':10)
  821.                    else write(output,'notforward':10);
  822.                    if externl then write(output,'extern':10)
  823.                    else write(output,'not extern':10);
  824.                  end
  825.                else write(output,'formal':10)
  826.              end
  827.              end
  828.         end (*case*);
  829.         writeln(output);
  830.         followctp(llink); followctp(rlink);
  831.         followstp(idtype)
  832.       end (*with*)
  833.     end (*followctp*);
  834.  
  835.   begin (*printtables*)
  836.     writeln(output); writeln(output); writeln(output);
  837.     if fb then lim := 0
  838.     else begin lim := top; write(output,' local') end;
  839.     writeln(output,' tables '); writeln(output);
  840.     marker;
  841.     for i := top downto lim do
  842.       followctp(display[i].fname);
  843.     writeln(output);
  844.     if not eol then write(output,' ':chcnt+16)
  845.   end (*printtables*);
  846.  
  847.   procedure genlabel(var nxtlab: integer);
  848.   begin intlabel := intlabel + 1;
  849.     nxtlab := intlabel
  850.   end (*genlabel*);
  851.  
  852.   procedure block(fsys: setofsys; fsy: symbol; fprocp: ctp);
  853.     var lsy: symbol; test: boolean;
  854.  
  855.     procedure skip(fsys: setofsys);
  856.       (*skip input string until relevant symbol found*)
  857.     begin
  858.       if not eof(input) then
  859.     begin while not(sy in fsys) and (not eof(input)) do insymbol;
  860.       if not (sy in fsys) then insymbol
  861.     end
  862.     end (*skip*) ;
  863.  
  864.     procedure constant(fsys: setofsys; var fsp: stp; var fvalu: valu);
  865.       var lsp: stp; lcp: ctp; sign: (none,pos,neg);
  866.       lvp: csp; i: 2..strglgth;
  867.     begin lsp := nil; fvalu.ival := 0;
  868.       if not(sy in constbegsys) then
  869.     begin error(50); skip(fsys+constbegsys) end;
  870.       if sy in constbegsys then
  871.     begin
  872.       if sy = stringconst then
  873.         begin
  874.           if lgth = 1 then lsp := charptr
  875.           else
  876.         begin
  877.           new(lsp,arrays);
  878.           with lsp^ do
  879.             begin aeltype := charptr; inxtype := nil;
  880.                size := lgth*charsize; form := arrays
  881.             end
  882.         end;
  883.           fvalu := val; insymbol
  884.         end
  885.       else
  886.         begin
  887.           sign := none;
  888.           if (sy = addop) and (op in [plus,minus]) then
  889.         begin if op = plus then sign := pos else sign := neg;
  890.           insymbol
  891.         end;
  892.           if sy = ident then
  893.         begin searchid([konst],lcp);
  894.           with lcp^ do
  895.             begin lsp := idtype; fvalu := values end;
  896.           if sign <> none then
  897.             if lsp = intptr then
  898.               begin if sign = neg then fvalu.ival := -fvalu.ival end
  899.             else
  900.               if lsp = realptr then
  901.             begin
  902.               if sign = neg then
  903.                 begin new(lvp,reel);
  904.                   if fvalu.valp^.rval[1] = '-' then
  905.                 lvp^.rval[1] := '+'
  906.                   else lvp^.rval[1] := '-';
  907.                   for i := 2 to strglgth do
  908.                 lvp^.rval[i] := fvalu.valp^.rval[i];
  909.                   fvalu.valp := lvp;
  910.                 end
  911.               end
  912.             else error(105);
  913.           insymbol;
  914.         end
  915.           else
  916.         if sy = intconst then
  917.           begin if sign = neg then val.ival := -val.ival;
  918.             lsp := intptr; fvalu := val; insymbol
  919.           end
  920.         else
  921.           if sy = realconst then
  922.             begin if sign = neg then val.valp^.rval[1] := '-';
  923.               lsp := realptr; fvalu := val; insymbol
  924.             end
  925.           else
  926.             begin error(106); skip(fsys) end
  927.         end;
  928.       if not (sy in fsys) then
  929.         begin error(6); skip(fsys) end
  930.       end;
  931.       fsp := lsp
  932.     end (*constant*) ;
  933.  
  934.     function equalbounds(fsp1,fsp2: stp): boolean;
  935.       var lmin1,lmin2,lmax1,lmax2: integer;
  936.     begin
  937.       if (fsp1=nil) or (fsp2=nil) then equalbounds := true
  938.       else
  939.     begin
  940.       getbounds(fsp1,lmin1,lmax1);
  941.       getbounds(fsp2,lmin2,lmax2);
  942.       equalbounds := (lmin1=lmin2) and (lmax1=lmax2)
  943.     end
  944.     end (*equalbounds*) ;
  945.  
  946.     function comptypes(fsp1,fsp2: stp) : boolean;
  947.       (*decide whether structures pointed at by fsp1 and fsp2 are compatible*)
  948.       var nxt1,nxt2: ctp; comp: boolean;
  949.     ltestp1,ltestp2 : testp;
  950.     begin
  951.       if fsp1 = fsp2 then comptypes := true
  952.       else
  953.     if (fsp1 <> nil) and (fsp2 <> nil) then
  954.       if fsp1^.form = fsp2^.form then
  955.         case fsp1^.form of
  956.           scalar:
  957.         comptypes := false;
  958.         (* identical scalars declared on different levels are
  959.          not recognized to be compatible*)
  960.           subrange:
  961.         comptypes := comptypes(fsp1^.rangetype,fsp2^.rangetype);
  962.           pointer:
  963.           begin
  964.             comp := false; ltestp1 := globtestp;
  965.             ltestp2 := globtestp;
  966.             while ltestp1 <> nil do
  967.               with ltestp1^ do
  968.             begin
  969.               if (elt1 = fsp1^.eltype) and
  970.                  (elt2 = fsp2^.eltype) then comp := true;
  971.               ltestp1 := lasttestp
  972.             end;
  973.             if not comp then
  974.               begin new(ltestp1);
  975.             with ltestp1^ do
  976.               begin elt1 := fsp1^.eltype;
  977.                 elt2 := fsp2^.eltype;
  978.                 lasttestp := globtestp
  979.               end;
  980.             globtestp := ltestp1;
  981.             comp := comptypes(fsp1^.eltype,fsp2^.eltype)
  982.               end;
  983.             comptypes := comp; globtestp := ltestp2
  984.           end;
  985.           power:
  986.         comptypes := comptypes(fsp1^.elset,fsp2^.elset);
  987.           arrays:
  988.         begin
  989.           comp := comptypes(fsp1^.aeltype,fsp2^.aeltype)
  990.               and comptypes(fsp1^.inxtype,fsp2^.inxtype);
  991.           comptypes := comp and (fsp1^.size = fsp2^.size) and
  992.               equalbounds(fsp1^.inxtype,fsp2^.inxtype)
  993.         end;
  994.           records:
  995.         begin nxt1 := fsp1^.fstfld; nxt2 := fsp2^.fstfld; comp:=true;
  996.           while (nxt1 <> nil) and (nxt2 <> nil) do
  997.             begin comp:=comp and comptypes(nxt1^.idtype,nxt2^.idtype);
  998.               nxt1 := nxt1^.next; nxt2 := nxt2^.next
  999.             end;
  1000.           comptypes := comp and (nxt1 = nil) and (nxt2 = nil)
  1001.                   and(fsp1^.recvar = nil)and(fsp2^.recvar = nil)
  1002.         end;
  1003.         (*identical records are recognized to be compatible
  1004.          iff no variants occur*)
  1005.           files:
  1006.         comptypes := comptypes(fsp1^.filtype,fsp2^.filtype)
  1007.         end (*case*)
  1008.       else (*fsp1^.form <> fsp2^.form*)
  1009.         if fsp1^.form = subrange then
  1010.           comptypes := comptypes(fsp1^.rangetype,fsp2)
  1011.         else
  1012.           if fsp2^.form = subrange then
  1013.         comptypes := comptypes(fsp1,fsp2^.rangetype)
  1014.           else comptypes := false
  1015.     else comptypes := true
  1016.     end (*comptypes*) ;
  1017.  
  1018.     function string(fsp: stp) : boolean;
  1019.     begin string := false;
  1020.       if fsp <> nil then
  1021.     if fsp^.form = arrays then
  1022.       if comptypes(fsp^.aeltype,charptr) then string := true
  1023.     end (*string*) ;
  1024.  
  1025.     procedure typ(fsys: setofsys; var fsp: stp; var fsize: addrrange);
  1026.       var lsp,lsp1,lsp2: stp; oldtop: disprange; lcp: ctp;
  1027.       lsize,displ: addrrange; lmin,lmax: integer;
  1028.  
  1029.       procedure simpletype(fsys:setofsys; var fsp:stp; var fsize:addrrange);
  1030.     var lsp,lsp1: stp; lcp,lcp1: ctp; ttop: disprange;
  1031.         lcnt: integer; lvalu: valu;
  1032.       begin fsize := 1;
  1033.     if not (sy in simptypebegsys) then
  1034.       begin error(1); skip(fsys + simptypebegsys) end;
  1035.     if sy in simptypebegsys then
  1036.       begin
  1037.         if sy = lparent then
  1038.           begin ttop := top;   (*decl. consts local to innermost block*)
  1039.         while display[top].occur <> blck do top := top - 1;
  1040.         new(lsp,scalar,declared);
  1041.         with lsp^ do
  1042.           begin size := intsize; form := scalar;
  1043.             scalkind := declared
  1044.           end;
  1045.         lcp1 := nil; lcnt := 0;
  1046.         repeat insymbol;
  1047.           if sy = ident then
  1048.             begin new(lcp,konst);
  1049.               with lcp^ do
  1050.             begin name := id; idtype := lsp; next := lcp1;
  1051.               values.ival := lcnt; klass := konst
  1052.             end;
  1053.               enterid(lcp);
  1054.               lcnt := lcnt + 1;
  1055.               lcp1 := lcp; insymbol
  1056.             end
  1057.           else error(2);
  1058.           if not (sy in fsys + [comma,rparent]) then
  1059.             begin error(6); skip(fsys + [comma,rparent]) end
  1060.         until sy <> comma;
  1061.         lsp^.fconst := lcp1; top := ttop;
  1062.         if sy = rparent then insymbol else error(4)
  1063.           end
  1064.         else
  1065.           begin
  1066.         if sy = ident then
  1067.           begin searchid([types,konst],lcp);
  1068.             insymbol;
  1069.             if lcp^.klass = konst then
  1070.               begin new(lsp,subrange);
  1071.             with lsp^, lcp^ do
  1072.               begin rangetype := idtype; form := subrange;
  1073.                 if string(rangetype) then
  1074.                   begin error(148); rangetype := nil end;
  1075.                 min := values; size := intsize
  1076.               end;
  1077.             if sy = colon then insymbol else error(5);
  1078.             constant(fsys,lsp1,lvalu);
  1079.             lsp^.max := lvalu;
  1080.             if lsp^.rangetype <> lsp1 then error(107)
  1081.               end
  1082.             else
  1083.               begin lsp := lcp^.idtype;
  1084.             if lsp <> nil then fsize := lsp^.size
  1085.               end
  1086.           end (*sy = ident*)
  1087.         else
  1088.           begin new(lsp,subrange); lsp^.form := subrange;
  1089.             constant(fsys + [colon],lsp1,lvalu);
  1090.             if string(lsp1) then
  1091.               begin error(148); lsp1 := nil end;
  1092.             with lsp^ do
  1093.               begin rangetype:=lsp1; min:=lvalu; size:=intsize end;
  1094.             if sy = colon then insymbol else error(5);
  1095.             constant(fsys,lsp1,lvalu);
  1096.             lsp^.max := lvalu;
  1097.             if lsp^.rangetype <> lsp1 then error(107)
  1098.           end;
  1099.         if lsp <> nil then
  1100.           with lsp^ do
  1101.             if form = subrange then
  1102.               if rangetype <> nil then
  1103.             if rangetype = realptr then error(399)
  1104.             else
  1105.               if min.ival > max.ival then error(102)
  1106.           end;
  1107.         fsp := lsp;
  1108.         if not (sy in fsys) then
  1109.           begin error(6); skip(fsys) end
  1110.       end
  1111.         else fsp := nil
  1112.       end (*simpletype*) ;
  1113.  
  1114.       procedure fieldlist(fsys: setofsys; var frecvar: stp);
  1115.     var lcp,lcp1,nxt,nxt1: ctp; lsp,lsp1,lsp2,lsp3,lsp4: stp;
  1116.         minsize,maxsize,lsize: addrrange; lvalu: valu;
  1117.       begin nxt1 := nil; lsp := nil;
  1118.     if not (sy in (fsys+[ident,casesy])) then
  1119.       begin error(19); skip(fsys + [ident,casesy]) end;
  1120.     while sy = ident do
  1121.       begin nxt := nxt1;
  1122.         repeat
  1123.           if sy = ident then
  1124.         begin new(lcp,field);
  1125.           with lcp^ do
  1126.             begin name := id; idtype := nil; next := nxt;
  1127.               klass := field
  1128.             end;
  1129.           nxt := lcp;
  1130.           enterid(lcp);
  1131.           insymbol
  1132.         end
  1133.           else error(2);
  1134.           if not (sy in [comma,colon]) then
  1135.         begin error(6); skip(fsys + [comma,colon,semicolon,casesy])
  1136.         end;
  1137.           test := sy <> comma;
  1138.           if not test  then insymbol
  1139.         until test;
  1140.         if sy = colon then insymbol else error(5);
  1141.         typ(fsys + [casesy,semicolon],lsp,lsize);
  1142.         while nxt <> nxt1 do
  1143.           with nxt^ do
  1144.         begin align(lsp,displ);
  1145.           idtype := lsp; fldaddr := displ;
  1146.           nxt := next; displ := displ + lsize
  1147.         end;
  1148.         nxt1 := lcp;
  1149.         while sy = semicolon do
  1150.           begin insymbol;
  1151.         if not (sy in fsys + [ident,casesy,semicolon]) then
  1152.           begin error(19); skip(fsys + [ident,casesy]) end
  1153.           end
  1154.       end (*while*);
  1155.     nxt := nil;
  1156.     while nxt1 <> nil do
  1157.       with nxt1^ do
  1158.         begin lcp := next; next := nxt; nxt := nxt1; nxt1 := lcp end;
  1159.     if sy = casesy then
  1160.       begin new(lsp,tagfld);
  1161.         with lsp^ do
  1162.           begin tagfieldp := nil; fstvar := nil; form:=tagfld end;
  1163.         frecvar := lsp;
  1164.         insymbol;
  1165.         if sy = ident then
  1166.           begin new(lcp,field);
  1167.         with lcp^ do
  1168.           begin name := id; idtype := nil; klass:=field;
  1169.             next := nil; fldaddr := displ
  1170.           end;
  1171.         enterid(lcp);
  1172.         insymbol;
  1173.         if sy = colon then insymbol else error(5);
  1174.         if sy = ident then
  1175.           begin searchid([types],lcp1);
  1176.             lsp1 := lcp1^.idtype;
  1177.             if lsp1 <> nil then
  1178.               begin align(lsp1,displ);
  1179.             lcp^.fldaddr := displ;
  1180.             displ := displ+lsp1^.size;
  1181.             if (lsp1^.form <= subrange) or string(lsp1) then
  1182.               begin if comptypes(realptr,lsp1) then error(109)
  1183.                 else if string(lsp1) then error(399);
  1184.                 lcp^.idtype := lsp1; lsp^.tagfieldp := lcp;
  1185.               end
  1186.             else error(110);
  1187.               end;
  1188.             insymbol;
  1189.           end
  1190.         else begin error(2); skip(fsys + [ofsy,lparent]) end
  1191.           end
  1192.         else begin error(2); skip(fsys + [ofsy,lparent]) end;
  1193.         lsp^.size := displ;
  1194.         if sy = ofsy then insymbol else error(8);
  1195.         lsp1 := nil; minsize := displ; maxsize := displ;
  1196.         repeat lsp2 := nil;
  1197.           if not (sy in fsys + [semicolon]) then
  1198.           begin
  1199.         repeat constant(fsys + [comma,colon,lparent],lsp3,lvalu);
  1200.           if lsp^.tagfieldp <> nil then
  1201.            if not comptypes(lsp^.tagfieldp^.idtype,lsp3)then error(111);
  1202.           new(lsp3,variant);
  1203.           with lsp3^ do
  1204.             begin nxtvar := lsp1; subvar := lsp2; varval := lvalu;
  1205.               form := variant
  1206.             end;
  1207.           lsp4 := lsp1;
  1208.           while lsp4 <> nil do
  1209.             with lsp4^ do
  1210.               begin
  1211.             if varval.ival = lvalu.ival then error(178);
  1212.             lsp4 := nxtvar
  1213.               end;
  1214.           lsp1 := lsp3; lsp2 := lsp3;
  1215.           test := sy <> comma;
  1216.           if not test then insymbol
  1217.         until test;
  1218.         if sy = colon then insymbol else error(5);
  1219.         if sy = lparent then insymbol else error(9);
  1220.         fieldlist(fsys + [rparent,semicolon],lsp2);
  1221.         if displ > maxsize then maxsize := displ;
  1222.         while lsp3 <> nil do
  1223.           begin lsp4 := lsp3^.subvar; lsp3^.subvar := lsp2;
  1224.             lsp3^.size := displ;
  1225.             lsp3 := lsp4
  1226.           end;
  1227.         if sy = rparent then
  1228.           begin insymbol;
  1229.             if not (sy in fsys + [semicolon]) then
  1230.               begin error(6); skip(fsys + [semicolon]) end
  1231.           end
  1232.         else error(4);
  1233.           end;
  1234.           test := sy <> semicolon;
  1235.           if not test then
  1236.         begin displ := minsize;
  1237.               insymbol
  1238.         end
  1239.         until test;
  1240.         displ := maxsize;
  1241.         lsp^.fstvar := lsp1;
  1242.       end
  1243.     else frecvar := nil
  1244.       end (*fieldlist*) ;
  1245.  
  1246.     begin (*typ*)
  1247.       if not (sy in typebegsys) then
  1248.      begin error(10); skip(fsys + typebegsys) end;
  1249.       if sy in typebegsys then
  1250.     begin
  1251.       if sy in simptypebegsys then simpletype(fsys,fsp,fsize)
  1252.       else
  1253.     (*^*)     if sy = arrow then
  1254.           begin new(lsp,pointer); fsp := lsp;
  1255.         with lsp^ do
  1256.           begin eltype := nil; size := ptrsize; form:=pointer end;
  1257.         insymbol;
  1258.         if sy = ident then
  1259.           begin prterr := false; (*no error if search not successful*)
  1260.             searchid([types],lcp); prterr := true;
  1261.             if lcp = nil then   (*forward referenced type id*)
  1262.               begin new(lcp,types);
  1263.             with lcp^ do
  1264.               begin name := id; idtype := lsp;
  1265.                 next := fwptr; klass := types
  1266.               end;
  1267.             fwptr := lcp
  1268.               end
  1269.             else
  1270.               begin
  1271.             if lcp^.idtype <> nil then
  1272.               if lcp^.idtype^.form = files then error(108)
  1273.               else lsp^.eltype := lcp^.idtype
  1274.               end;
  1275.             insymbol;
  1276.           end
  1277.         else error(2);
  1278.           end
  1279.         else
  1280.           begin
  1281.         if sy = packedsy then
  1282.           begin insymbol;
  1283.             if not (sy in typedels) then
  1284.               begin
  1285.             error(10); skip(fsys + typedels)
  1286.               end
  1287.           end;
  1288.     (*array*)     if sy = arraysy then
  1289.           begin insymbol;
  1290.             if sy = lbrack then insymbol else error(11);
  1291.             lsp1 := nil;
  1292.             repeat new(lsp,arrays);
  1293.               with lsp^ do
  1294.             begin aeltype := lsp1; inxtype := nil; form:=arrays end;
  1295.               lsp1 := lsp;
  1296.               simpletype(fsys + [comma,rbrack,ofsy],lsp2,lsize);
  1297.               lsp1^.size := lsize;
  1298.               if lsp2 <> nil then
  1299.             if lsp2^.form <= subrange then
  1300.               begin
  1301.                 if lsp2 = realptr then
  1302.                   begin error(109); lsp2 := nil end
  1303.                 else
  1304.                   if lsp2 = intptr then
  1305.                 begin error(149); lsp2 := nil end;
  1306.                 lsp^.inxtype := lsp2
  1307.               end
  1308.             else begin error(113); lsp2 := nil end;
  1309.               test := sy <> comma;
  1310.               if not test then insymbol
  1311.             until test;
  1312.             if sy = rbrack then insymbol else error(12);
  1313.             if sy = ofsy then insymbol else error(8);
  1314.             typ(fsys,lsp,lsize);
  1315.             repeat
  1316.               with lsp1^ do
  1317.             begin lsp2 := aeltype; aeltype := lsp;
  1318.               if inxtype <> nil then
  1319.                 begin getbounds(inxtype,lmin,lmax);
  1320.                   align(lsp,lsize);
  1321.                   lsize := lsize*(lmax - lmin + 1);
  1322.                   size := lsize
  1323.                 end
  1324.             end;
  1325.               lsp := lsp1; lsp1 := lsp2
  1326.             until lsp1 = nil
  1327.           end
  1328.         else
  1329.     (*record*)      if sy = recordsy then
  1330.             begin insymbol;
  1331.               oldtop := top;
  1332.               if top < displimit then
  1333.             begin top := top + 1;
  1334.               with display[top] do
  1335.                 begin fname := nil;
  1336.                   flabel := nil;
  1337.                   occur := rec
  1338.                 end
  1339.             end
  1340.               else error(250);
  1341.               displ := 0;
  1342.               fieldlist(fsys-[semicolon]+[endsy],lsp1);
  1343.               new(lsp,records);
  1344.               with lsp^ do
  1345.             begin fstfld := display[top].fname;
  1346.               recvar := lsp1; size := displ; form := records
  1347.             end;
  1348.               top := oldtop;
  1349.               if sy = endsy then insymbol else error(13)
  1350.             end
  1351.           else
  1352.     (*set*)       if sy = setsy then
  1353.               begin insymbol;
  1354.             if sy = ofsy then insymbol else error(8);
  1355.             simpletype(fsys,lsp1,lsize);
  1356.             if lsp1 <> nil then
  1357.               if lsp1^.form > subrange then
  1358.                 begin error(115); lsp1 := nil end
  1359.               else
  1360.                 if lsp1 = realptr then
  1361.                   begin error(114); lsp1 := nil end
  1362.                 else if lsp1 = intptr then
  1363.                   begin error(169); lsp1 := nil end
  1364.                 else
  1365.                   begin getbounds(lsp1,lmin,lmax);
  1366.                 if (lmin < setlow) or (lmax > sethigh)
  1367.                   then error(169);
  1368.                   end;
  1369.             new(lsp,power);
  1370.             with lsp^ do
  1371.               begin elset:=lsp1; size:=setsize; form:=power end;
  1372.               end
  1373.             else
  1374.     (*file*)        if sy = filesy then
  1375.               begin insymbol;
  1376.                 error(399); skip(fsys); lsp := nil
  1377.               end;
  1378.         fsp := lsp
  1379.           end;
  1380.       if not (sy in fsys) then
  1381.         begin error(6); skip(fsys) end
  1382.     end
  1383.       else fsp := nil;
  1384.       if fsp = nil then fsize := 1 else fsize := fsp^.size
  1385.     end (*typ*) ;
  1386.  
  1387.     procedure labeldeclaration;
  1388.       var llp: lbp; redef: boolean; lbname: integer;
  1389.     begin
  1390.       repeat
  1391.     if sy = intconst then
  1392.       with display[top] do
  1393.         begin llp := flabel; redef := false;
  1394.           while (llp <> nil) and not redef do
  1395.         if llp^.labval <> val.ival then
  1396.           llp := llp^.nextlab
  1397.         else begin redef := true; error(166) end;
  1398.           if not redef then
  1399.         begin new(llp);
  1400.           with llp^ do
  1401.             begin labval := val.ival; genlabel(lbname);
  1402.               defined := false; nextlab := flabel; labname := lbname
  1403.             end;
  1404.           flabel := llp
  1405.         end;
  1406.           insymbol
  1407.         end
  1408.     else error(15);
  1409.     if not ( sy in fsys + [comma, semicolon] ) then
  1410.       begin error(6); skip(fsys+[comma,semicolon]) end;
  1411.     test := sy <> comma;
  1412.     if not test then insymbol
  1413.       until test;
  1414.       if sy = semicolon then insymbol else error(14)
  1415.     end (* labeldeclaration *) ;
  1416.  
  1417.     procedure constdeclaration;
  1418.       var lcp: ctp; lsp: stp; lvalu: valu;
  1419.     begin
  1420.       if sy <> ident then
  1421.     begin error(2); skip(fsys + [ident]) end;
  1422.       while sy = ident do
  1423.     begin new(lcp,konst);
  1424.       with lcp^ do
  1425.         begin name := id; idtype := nil; next := nil; klass:=konst end;
  1426.       insymbol;
  1427.       if (sy = relop) and (op = eqop) then insymbol else error(16);
  1428.       constant(fsys + [semicolon],lsp,lvalu);
  1429.       enterid(lcp);
  1430.       lcp^.idtype := lsp; lcp^.values := lvalu;
  1431.       if sy = semicolon then
  1432.         begin insymbol;
  1433.           if not (sy in fsys + [ident]) then
  1434.         begin error(6); skip(fsys + [ident]) end
  1435.         end
  1436.       else error(14)
  1437.     end
  1438.     end (*constdeclaration*) ;
  1439.  
  1440.     procedure typedeclaration;
  1441.       var lcp,lcp1,lcp2: ctp; lsp: stp; lsize: addrrange;
  1442.     begin
  1443.       if sy <> ident then
  1444.     begin error(2); skip(fsys + [ident]) end;
  1445.       while sy = ident do
  1446.     begin new(lcp,types);
  1447.       with lcp^ do
  1448.         begin name := id; idtype := nil; klass := types end;
  1449.       insymbol;
  1450.       if (sy = relop) and (op = eqop) then insymbol else error(16);
  1451.       typ(fsys + [semicolon],lsp,lsize);
  1452.       enterid(lcp);
  1453.       lcp^.idtype := lsp;
  1454.       (*has any forward reference been satisfied:*)
  1455.       lcp1 := fwptr;
  1456.       while lcp1 <> nil do
  1457.         begin
  1458.           if lcp1^.name = lcp^.name then
  1459.         begin lcp1^.idtype^.eltype := lcp^.idtype;
  1460.           if lcp1 <> fwptr then
  1461.             lcp2^.next := lcp1^.next
  1462.           else fwptr := lcp1^.next;
  1463.         end
  1464.           else lcp2 := lcp1;
  1465.           lcp1 := lcp1^.next
  1466.         end;
  1467.       if sy = semicolon then
  1468.         begin insymbol;
  1469.           if not (sy in fsys + [ident]) then
  1470.         begin error(6); skip(fsys + [ident]) end
  1471.         end
  1472.       else error(14)
  1473.     end;
  1474.       if fwptr <> nil then
  1475.     begin error(117); writeln(output);
  1476.       repeat writeln(output,' type-id ',fwptr^.name);
  1477.         fwptr := fwptr^.next
  1478.       until fwptr = nil;
  1479.       if not eol then write(output,' ': chcnt+16)
  1480.     end
  1481.     end (*typedeclaration*) ;
  1482.  
  1483.     procedure vardeclaration;
  1484.       var lcp,nxt: ctp; lsp: stp; lsize: addrrange;
  1485.     begin nxt := nil;
  1486.       repeat
  1487.     repeat
  1488.       if sy = ident then
  1489.         begin new(lcp,vars);
  1490.           with lcp^ do
  1491.            begin name := id; next := nxt; klass := vars;
  1492.           idtype := nil; vkind := actual; vlev := level
  1493.         end;
  1494.           enterid(lcp);
  1495.           nxt := lcp;
  1496.           insymbol;
  1497.         end
  1498.       else error(2);
  1499.       if not (sy in fsys + [comma,colon] + typedels) then
  1500.         begin error(6); skip(fsys+[comma,colon,semicolon]+typedels) end;
  1501.       test := sy <> comma;
  1502.       if not test then insymbol
  1503.     until test;
  1504.     if sy = colon then insymbol else error(5);
  1505.     typ(fsys + [semicolon] + typedels,lsp,lsize);
  1506.     while nxt <> nil do
  1507.       with  nxt^ do
  1508.         begin align(lsp,lc);
  1509.           idtype := lsp; vaddr := lc;
  1510.           lc := lc + lsize; nxt := next
  1511.         end;
  1512.     if sy = semicolon then
  1513.       begin insymbol;
  1514.         if not (sy in fsys + [ident]) then
  1515.           begin error(6); skip(fsys + [ident]) end
  1516.       end
  1517.     else error(14)
  1518.       until (sy <> ident) and not (sy in typedels);
  1519.       if fwptr <> nil then
  1520.     begin error(117); writeln(output);
  1521.       repeat writeln(output,' type-id ',fwptr^.name);
  1522.         fwptr := fwptr^.next
  1523.       until fwptr = nil;
  1524.       if not eol then write(output,' ': chcnt+16)
  1525.     end
  1526.     end (*vardeclaration*) ;
  1527.  
  1528.     procedure procdeclaration(fsy: symbol);
  1529.       var oldlev: 0..maxlevel; lcp,lcp1: ctp; lsp: stp;
  1530.       forw: boolean; oldtop: disprange;
  1531.       llc,lcm: addrrange; lbname: integer; markp: marktype;
  1532.  
  1533.       procedure parameterlist(fsy: setofsys; var fpar: ctp);
  1534.     var lcp,lcp1,lcp2,lcp3: ctp; lsp: stp; lkind: idkind;
  1535.       llc,lsize: addrrange; count: integer;
  1536.       begin lcp1 := nil;
  1537.     if not (sy in fsy + [lparent]) then
  1538.       begin error(7); skip(fsys + fsy + [lparent]) end;
  1539.     if sy = lparent then
  1540.       begin if forw then error(119);
  1541.         insymbol;
  1542.         if not (sy in [ident,varsy,procsy,funcsy]) then
  1543.           begin error(7); skip(fsys + [ident,rparent]) end;
  1544.         while sy in [ident,varsy,procsy,funcsy] do
  1545.           begin
  1546.         if sy = procsy then
  1547.           begin error(399);
  1548.             repeat insymbol;
  1549.               if sy = ident then
  1550.             begin new(lcp,proc,declared,formal);
  1551.               with lcp^ do
  1552.                 begin name := id; idtype := nil; next := lcp1;
  1553.                   pflev := level (*beware of parameter procedures*);
  1554.                   klass:=proc;pfdeckind:=declared;pfkind:=formal
  1555.                 end;
  1556.               enterid(lcp);
  1557.               lcp1 := lcp;
  1558.               align(parmptr,lc);
  1559.               (*lc := lc + some size *)
  1560.               insymbol
  1561.             end
  1562.               else error(2);
  1563.               if not (sy in fsys + [comma,semicolon,rparent]) then
  1564.             begin error(7);skip(fsys+[comma,semicolon,rparent])end
  1565.             until sy <> comma
  1566.           end
  1567.         else
  1568.           begin
  1569.             if sy = funcsy then
  1570.               begin error(399); lcp2 := nil;
  1571.             repeat insymbol;
  1572.               if sy = ident then
  1573.                 begin new(lcp,func,declared,formal);
  1574.                   with lcp^ do
  1575.                 begin name := id; idtype := nil; next := lcp2;
  1576.                   pflev := level (*beware param funcs*);
  1577.                   klass:=func;pfdeckind:=declared;
  1578.                   pfkind:=formal
  1579.                 end;
  1580.                   enterid(lcp);
  1581.                  lcp2 := lcp;
  1582.                  align(parmptr,lc);
  1583.                  (*lc := lc + some size*)
  1584.                   insymbol;
  1585.                 end;
  1586.               if not (sy in [comma,colon] + fsys) then
  1587.                 begin error(7);skip(fsys+[comma,semicolon,rparent])
  1588.                 end
  1589.             until sy <> comma;
  1590.             if sy = colon then
  1591.               begin insymbol;
  1592.                 if sy = ident then
  1593.                   begin searchid([types],lcp);
  1594.                 lsp := lcp^.idtype;
  1595.                 if lsp <> nil then
  1596.                  if not(lsp^.form in[scalar,subrange,pointer])
  1597.                     then begin error(120); lsp := nil end;
  1598.                 lcp3 := lcp2;
  1599.                 while lcp2 <> nil do
  1600.                   begin lcp2^.idtype := lsp; lcp := lcp2;
  1601.                     lcp2 := lcp2^.next
  1602.                   end;
  1603.                 lcp^.next := lcp1; lcp1 := lcp3;
  1604.                 insymbol
  1605.                   end
  1606.                 else error(2);
  1607.                 if not (sy in fsys + [semicolon,rparent]) then
  1608.                   begin error(7);skip(fsys+[semicolon,rparent])end
  1609.               end
  1610.             else error(5)
  1611.               end
  1612.             else
  1613.               begin
  1614.             if sy = varsy then
  1615.               begin lkind := formal; insymbol end
  1616.             else lkind := actual;
  1617.             lcp2 := nil;
  1618.             count := 0;
  1619.             repeat
  1620.               if sy = ident then
  1621.                 begin new(lcp,vars);
  1622.                   with lcp^ do
  1623.                 begin name:=id; idtype:=nil; klass:=vars;
  1624.                   vkind := lkind; next := lcp2; vlev := level;
  1625.                 end;
  1626.                   enterid(lcp);
  1627.                   lcp2 := lcp; count := count+1;
  1628.                   insymbol;
  1629.                 end;
  1630.               if not (sy in [comma,colon] + fsys) then
  1631.                 begin error(7);skip(fsys+[comma,semicolon,rparent])
  1632.                 end;
  1633.               test := sy <> comma;
  1634.               if not test then insymbol
  1635.             until test;
  1636.             if sy = colon then
  1637.               begin insymbol;
  1638.                 if sy = ident then
  1639.                   begin searchid([types],lcp);
  1640.                 lsp := lcp^.idtype;
  1641.                 lsize := ptrsize;
  1642.                 if lsp <> nil then
  1643.                   if lkind=actual then
  1644.                     if lsp^.form<=power then lsize := lsp^.size
  1645.                     else if lsp^.form=files then error(121);
  1646.                 align(parmptr,lsize);
  1647.                 lcp3 := lcp2;
  1648.                 align(parmptr,lc);
  1649.                 lc := lc+count*lsize;
  1650.                 llc := lc;
  1651.                 while lcp2 <> nil do
  1652.                   begin lcp := lcp2;
  1653.                     with lcp2^ do
  1654.                       begin idtype := lsp;
  1655.                     llc := llc-lsize;
  1656.                     vaddr := llc;
  1657.                       end;
  1658.                     lcp2 := lcp2^.next
  1659.                   end;
  1660.                 lcp^.next := lcp1; lcp1 := lcp3;
  1661.                 insymbol
  1662.                   end
  1663.                 else error(2);
  1664.                 if not (sy in fsys + [semicolon,rparent]) then
  1665.                   begin error(7);skip(fsys+[semicolon,rparent])end
  1666.               end
  1667.             else error(5);
  1668.               end;
  1669.           end;
  1670.         if sy = semicolon then
  1671.           begin insymbol;
  1672.             if not (sy in fsys + [ident,varsy,procsy,funcsy]) then
  1673.               begin error(7); skip(fsys + [ident,rparent]) end
  1674.           end
  1675.           end (*while*) ;
  1676.         if sy = rparent then
  1677.           begin insymbol;
  1678.         if not (sy in fsy + fsys) then
  1679.           begin error(6); skip(fsy + fsys) end
  1680.           end
  1681.         else error(4);
  1682.         lcp3 := nil;
  1683.         (*reverse pointers and reserve local cells for copies of multiple
  1684.          values*)
  1685.         while lcp1 <> nil do
  1686.           with lcp1^ do
  1687.         begin lcp2 := next; next := lcp3;
  1688.           if klass = vars then
  1689.             if idtype <> nil then
  1690.               if (vkind=actual)and(idtype^.form>power) then
  1691.             begin align(idtype,lc);
  1692.               vaddr := lc;
  1693.               lc := lc+idtype^.size;
  1694.             end;
  1695.           lcp3 := lcp1; lcp1 := lcp2
  1696.         end;
  1697.         fpar := lcp3
  1698.       end
  1699.         else fpar := nil
  1700.     end (*parameterlist*) ;
  1701.  
  1702.     begin (*procdeclaration*)
  1703.       llc := lc; lc := lcaftermarkstack; forw := false;
  1704.       if sy = ident then
  1705.     begin searchsection(display[top].fname,lcp); (*decide whether forw.*)
  1706.       if lcp <> nil then
  1707.         begin
  1708.           if lcp^.klass = proc then
  1709.         forw := lcp^.forwdecl and(fsy=procsy)and(lcp^.pfkind=actual)
  1710.           else
  1711.         if lcp^.klass = func then
  1712.           forw:=lcp^.forwdecl and(fsy=funcsy)and(lcp^.pfkind=actual)
  1713.         else forw := false;
  1714.           if not forw then error(160)
  1715.         end;
  1716.       if not forw then
  1717.         begin
  1718.           if fsy = procsy then new(lcp,proc,declared,actual)
  1719.           else new(lcp,func,declared,actual);
  1720.           with lcp^ do
  1721.         begin name := id; idtype := nil;
  1722.           externl := false; pflev := level; genlabel(lbname);
  1723.           pfdeckind := declared; pfkind := actual; pfname := lbname;
  1724.           if fsy = procsy then klass := proc
  1725.           else klass := func
  1726.         end;
  1727.           enterid(lcp)
  1728.         end
  1729.       else
  1730.         begin lcp1 := lcp^.next;
  1731.           while lcp1 <> nil do
  1732.         begin
  1733.           with lcp1^ do
  1734.             if klass = vars then
  1735.               if idtype <> nil then
  1736.             begin lcm := vaddr + idtype^.size;
  1737.               if lcm > lc then lc := lcm
  1738.             end;
  1739.           lcp1 := lcp1^.next
  1740.         end
  1741.         end;
  1742.       insymbol
  1743.     end
  1744.       else
  1745.     begin error(2); lcp := ufctptr end;
  1746.       oldlev := level; oldtop := top;
  1747.       if level < maxlevel then level := level + 1 else error(251);
  1748.       if top < displimit then
  1749.     begin top := top + 1;
  1750.       with display[top] do
  1751.         begin
  1752.           if forw then fname := lcp^.next
  1753.           else fname := nil;
  1754.           flabel := nil;
  1755.           occur := blck
  1756.         end
  1757.     end
  1758.       else error(250);
  1759.       if fsy = procsy then
  1760.     begin parameterlist([semicolon],lcp1);
  1761.       if not forw then lcp^.next := lcp1
  1762.     end
  1763.       else
  1764.     begin parameterlist([semicolon,colon],lcp1);
  1765.       if not forw then lcp^.next := lcp1;
  1766.       if sy = colon then
  1767.         begin insymbol;
  1768.           if sy = ident then
  1769.         begin if forw then error(122);
  1770.           searchid([types],lcp1);
  1771.           lsp := lcp1^.idtype;
  1772.           lcp^.idtype := lsp;
  1773.           if lsp <> nil then
  1774.             if not (lsp^.form in [scalar,subrange,pointer]) then
  1775.               begin error(120); lcp^.idtype := nil end;
  1776.           insymbol
  1777.         end
  1778.           else begin error(2); skip(fsys + [semicolon]) end
  1779.         end
  1780.       else
  1781.         if not forw then error(123)
  1782.     end;
  1783.       if sy = semicolon then insymbol else error(14);
  1784.       if sy = forwardsy then
  1785.     begin
  1786.       if forw then error(161)
  1787.       else lcp^.forwdecl := true;
  1788.       insymbol;
  1789.       if sy = semicolon then insymbol else error(14);
  1790.       if not (sy in fsys) then
  1791.         begin error(6); skip(fsys) end
  1792.     end
  1793.       else
  1794.     begin lcp^.forwdecl := false; mark(markp);
  1795.       repeat block(fsys,semicolon,lcp);
  1796.         if sy = semicolon then
  1797.           begin if prtables then printtables(false); insymbol;
  1798.         if not (sy in [beginsy,procsy,funcsy]) then
  1799.           begin error(6); skip(fsys) end
  1800.           end
  1801.         else error(14)
  1802.       until (sy in [beginsy,procsy,funcsy]) or eof(input);
  1803.       release(markp); (* return local entries on runtime heap *)
  1804.     end;
  1805.       level := oldlev; top := oldtop; lc := llc;
  1806.     end (*procdeclaration*) ;
  1807.  
  1808.     procedure body(fsys: setofsys);
  1809.       const cstoccmax=65; cixmax=1000;
  1810.       type oprange = 0..63;
  1811.       var
  1812.       llcp:ctp; saveid:alpha;
  1813.       cstptr: array [1..cstoccmax] of csp;
  1814.       cstptrix: 0..cstoccmax;
  1815.       (*allows referencing of noninteger constants by an index
  1816.        (instead of a pointer), which can be stored in the p2-field
  1817.        of the instruction record until writeout.
  1818.        --> procedure load, procedure writeout*)
  1819.       entname, segsize: integer;
  1820.       stacktop, topnew, topmax: integer;
  1821.       lcmax,llc1: addrrange; lcp: ctp;
  1822.       llp: lbp;
  1823.  
  1824.  
  1825.       procedure mes(i: integer);
  1826.       begin topnew := topnew + cdx[i]*maxstack;
  1827.     if topnew > topmax then topmax := topnew
  1828.       end;
  1829.  
  1830.       procedure putic;
  1831.       begin if ic mod 10 = 0 then writeln(prr,'i',ic:5) end;
  1832.  
  1833.       procedure gen0(fop: oprange);
  1834.       begin
  1835.     if prcode then begin putic; writeln(prr,mn[fop]:4) end;
  1836.     ic := ic + 1; mes(fop)
  1837.       end (*gen0*) ;
  1838.  
  1839.       procedure gen1(fop: oprange; fp2: integer);
  1840.     var k: integer;
  1841.       begin
  1842.     if prcode then
  1843.       begin putic; write(prr,mn[fop]:4);
  1844.         if fop = 30 then
  1845.           begin writeln(prr,sna[fp2]:12);
  1846.         topnew := topnew + pdx[fp2]*maxstack;
  1847.         if topnew > topmax then topmax := topnew
  1848.           end
  1849.         else
  1850.           begin
  1851.         if fop = 38 then
  1852.            begin write(prr,'''');
  1853.              with cstptr[fp2]^ do
  1854.              begin
  1855.                for k := 1 to slgth do write(prr,sval[k]:1);
  1856.                for k := slgth+1 to strglgth do write(prr,' ');
  1857.              end;
  1858.              writeln(prr,'''')
  1859.            end
  1860.         else if fop = 42 then writeln(prr,chr(fp2))
  1861.              else writeln(prr,fp2:12);
  1862.         mes(fop)
  1863.           end
  1864.       end;
  1865.     ic := ic + 1
  1866.       end (*gen1*) ;
  1867.  
  1868.       procedure gen2(fop: oprange; fp1,fp2: integer);
  1869.     var k : integer;
  1870.       begin
  1871.     if prcode then
  1872.       begin putic; write(prr,mn[fop]:4);
  1873.         case fop of
  1874.           45,50,54,56:
  1875.         writeln(prr,' ',fp1:3,fp2:8);
  1876.           47,48,49,52,53,55:
  1877.         begin write(prr,chr(fp1));
  1878.           if chr(fp1) = 'm' then write(prr,fp2:11);
  1879.           writeln(prr)
  1880.         end;
  1881.           51:
  1882.         case fp1 of
  1883.           1: writeln(prr,'i ',fp2);
  1884.           2: begin write(prr,'r ');
  1885.                with cstptr[fp2]^ do
  1886.              for k := 1 to strglgth do write(prr,rval[k]);
  1887.                writeln(prr)
  1888.              end;
  1889.           3: writeln(prr,'b ',fp2);
  1890.           4: writeln(prr,'n');
  1891.           6: writeln(prr,'c ''':3,chr(fp2),'''');
  1892.           5: begin write(prr,'(');
  1893.                with cstptr[fp2]^ do
  1894.              for k := setlow to sethigh do
  1895.                if k in pval then write(prr,k:3);
  1896.                writeln(prr,')')
  1897.              end
  1898.         end
  1899.         end;
  1900.       end;
  1901.     ic := ic + 1; mes(fop)
  1902.       end (*gen2*) ;
  1903.  
  1904.       procedure gentypindicator(fsp: stp);
  1905.       begin
  1906.     if fsp<>nil then
  1907.       with fsp^ do
  1908.         case form of
  1909.          scalar: if fsp=intptr then write(prr,'i')
  1910.              else
  1911.                if fsp=boolptr then write(prr,'b')
  1912.                else
  1913.              if fsp=charptr then write(prr,'c')
  1914.              else
  1915.                if scalkind = declared then write(prr,'i')
  1916.                else write(prr,'r');
  1917.          subrange: gentypindicator(rangetype);
  1918.          pointer:  write(prr,'a');
  1919.          power:    write(prr,'s');
  1920.          records,arrays: write(prr,'m');
  1921.          files,tagfld,variant: error(500)
  1922.         end
  1923.       end (*typindicator*);
  1924.  
  1925.       procedure gen0t(fop: oprange; fsp: stp);
  1926.       begin
  1927.     if prcode then
  1928.       begin putic;
  1929.         write(prr,mn[fop]:4);
  1930.         gentypindicator(fsp);
  1931.         writeln(prr);
  1932.       end;
  1933.     ic := ic + 1; mes(fop)
  1934.       end (*gen0t*);
  1935.  
  1936.       procedure gen1t(fop: oprange; fp2: integer; fsp: stp);
  1937.       begin
  1938.     if prcode then
  1939.       begin putic;
  1940.         write(prr,mn[fop]:4);
  1941.         gentypindicator(fsp);
  1942.         writeln(prr,fp2:11)
  1943.       end;
  1944.     ic := ic + 1; mes(fop)
  1945.       end (*gen1t*);
  1946.  
  1947.       procedure gen2t(fop: oprange; fp1,fp2: integer; fsp: stp);
  1948.       begin
  1949.     if prcode then
  1950.       begin putic;
  1951.         write(prr,mn[fop]: 4);
  1952.         gentypindicator(fsp);
  1953.         writeln(prr,fp1:3+5*ord(abs(fp1)>99),fp2:8);
  1954.       end;
  1955.     ic := ic + 1; mes(fop)
  1956.       end (*gen2t*);
  1957.  
  1958.       procedure load;
  1959.       begin
  1960.     with gattr do
  1961.       if typtr <> nil then
  1962.         begin
  1963.           case kind of
  1964.         cst:   if (typtr^.form = scalar) and (typtr <> realptr) then
  1965.              if typtr = boolptr then gen2(51(*ldc*),3,cval.ival)
  1966.              else
  1967.                if typtr=charptr then
  1968.                  gen2(51(*ldc*),6,cval.ival)
  1969.                else gen2(51(*ldc*),1,cval.ival)
  1970.                else
  1971.              if typtr = nilptr then gen2(51(*ldc*),4,0)
  1972.              else
  1973.                if cstptrix >= cstoccmax then error(254)
  1974.                else
  1975.                  begin cstptrix := cstptrix + 1;
  1976.                    cstptr[cstptrix] := cval.valp;
  1977.                    if typtr = realptr then
  1978.                  gen2(51(*ldc*),2,cstptrix)
  1979.                    else
  1980.                  gen2(51(*ldc*),5,cstptrix)
  1981.                  end;
  1982.         varbl: case access of
  1983.              drct:   if vlevel<=1 then
  1984.                    gen1t(39(*ldo*),dplmt,typtr)
  1985.                  else gen2t(54(*lod*),level-vlevel,dplmt,typtr);
  1986.              indrct: gen1t(35(*ind*),idplmt,typtr);
  1987.              inxd:   error(400)
  1988.                end;
  1989.         expr:
  1990.           end;
  1991.           kind := expr
  1992.         end
  1993.       end (*load*) ;
  1994.  
  1995.       procedure store(var fattr: attr);
  1996.       begin
  1997.     with fattr do
  1998.       if typtr <> nil then
  1999.         case access of
  2000.           drct:   if vlevel <= 1 then gen1t(43(*sro*),dplmt,typtr)
  2001.               else gen2t(56(*str*),level-vlevel,dplmt,typtr);
  2002.           indrct: if idplmt <> 0 then error(400)
  2003.               else gen0t(26(*sto*),typtr);
  2004.           inxd:   error(400)
  2005.         end
  2006.       end (*store*) ;
  2007.  
  2008.       procedure loadaddress;
  2009.       begin
  2010.     with gattr do
  2011.       if typtr <> nil then
  2012.         begin
  2013.           case kind of
  2014.         cst:   if string(typtr) then
  2015.              if cstptrix >= cstoccmax then error(254)
  2016.              else
  2017.                begin cstptrix := cstptrix + 1;
  2018.                  cstptr[cstptrix] := cval.valp;
  2019.                  gen1(38(*lca*),cstptrix)
  2020.                end
  2021.                else error(400);
  2022.         varbl: case access of
  2023.              drct:   if vlevel <= 1 then gen1(37(*lao*),dplmt)
  2024.                  else gen2(50(*lda*),level-vlevel,dplmt);
  2025.              indrct: if idplmt <> 0 then
  2026.                    gen1t(34(*inc*),idplmt,nilptr);
  2027.              inxd:   error(400)
  2028.                end;
  2029.         expr:  error(400)
  2030.           end;
  2031.           kind := varbl; access := indrct; idplmt := 0
  2032.         end
  2033.       end (*loadaddress*) ;
  2034.  
  2035.  
  2036.       procedure genfjp(faddr: integer);
  2037.       begin load;
  2038.     if gattr.typtr <> nil then
  2039.       if gattr.typtr <> boolptr then error(144);
  2040.     if prcode then begin putic; writeln(prr,mn[33]:4,' l':8,faddr:4) end;
  2041.     ic := ic + 1; mes(33)
  2042.       end (*genfjp*) ;
  2043.  
  2044.       procedure genujpxjp(fop: oprange; fp2: integer);
  2045.       begin
  2046.        if prcode then
  2047.       begin putic; writeln(prr, mn[fop]:4, ' l':8,fp2:4) end;
  2048.     ic := ic + 1; mes(fop)
  2049.       end (*genujpxjp*);
  2050.  
  2051.  
  2052.       procedure gencupent(fop: oprange; fp1,fp2: integer);
  2053.       begin
  2054.     if prcode then
  2055.       begin putic;
  2056.         writeln(prr,mn[fop]:4,fp1:4,'l':4,fp2:4)
  2057.       end;
  2058.     ic := ic + 1; mes(fop)
  2059.       end;
  2060.  
  2061.  
  2062.       procedure checkbnds(fsp: stp);
  2063.     var lmin,lmax: integer;
  2064.       begin
  2065.     if fsp <> nil then
  2066.       if fsp <> intptr then
  2067.         if fsp <> realptr then
  2068.           if fsp^.form <= subrange then
  2069.         begin
  2070.           getbounds(fsp,lmin,lmax);
  2071.           gen2t(45(*chk*),lmin,lmax,fsp)
  2072.         end
  2073.       end (*checkbnds*);
  2074.  
  2075.  
  2076.       procedure putlabel(labname: integer);
  2077.       begin if prcode then writeln(prr, 'l', labname:4)
  2078.       end (*putlabel*);
  2079.  
  2080.       procedure statement(fsys: setofsys);
  2081.     label 1;
  2082.     var lcp: ctp; llp: lbp;
  2083.  
  2084.     procedure expression(fsys: setofsys); forward;
  2085.  
  2086.     procedure selector(fsys: setofsys; fcp: ctp);
  2087.     var lattr: attr; lcp: ctp; lsize: addrrange; lmin,lmax: integer;
  2088.     begin
  2089.       with fcp^, gattr do
  2090.         begin typtr := idtype; kind := varbl;
  2091.           case klass of
  2092.         vars:
  2093.           if vkind = actual then
  2094.             begin access := drct; vlevel := vlev;
  2095.               dplmt := vaddr
  2096.             end
  2097.           else
  2098.             begin gen2t(54(*lod*),level-vlev,vaddr,nilptr);
  2099.               access := indrct; idplmt := 0
  2100.             end;
  2101.         field:
  2102.           with display[disx] do
  2103.             if occur = crec then
  2104.               begin access := drct; vlevel := clev;
  2105.             dplmt := cdspl + fldaddr
  2106.               end
  2107.             else
  2108.               begin
  2109.             if level = 1 then gen1t(39(*ldo*),vdspl,nilptr)
  2110.             else gen2t(54(*lod*),0,vdspl,nilptr);
  2111.             access := indrct; idplmt := fldaddr
  2112.               end;
  2113.         func:
  2114.           if pfdeckind = standard then
  2115.             begin error(150); typtr := nil end
  2116.           else
  2117.             begin
  2118.               if pfkind = formal then error(151)
  2119.               else
  2120.             if (pflev+1<>level)or(fprocp<>fcp) then error(177);
  2121.             begin access := drct; vlevel := pflev + 1;
  2122.               dplmt := 0   (*impl. relat. addr. of fct. result*)
  2123.             end
  2124.             end
  2125.           end (*case*)
  2126.         end (*with*);
  2127.       if not (sy in selectsys + fsys) then
  2128.         begin error(59); skip(selectsys + fsys) end;
  2129.       while sy in selectsys do
  2130.         begin
  2131.     (*[*) if sy = lbrack then
  2132.         begin
  2133.           repeat lattr := gattr;
  2134.             with lattr do
  2135.               if typtr <> nil then
  2136.             if typtr^.form <> arrays then
  2137.               begin error(138); typtr := nil end;
  2138.             loadaddress;
  2139.             insymbol; expression(fsys + [comma,rbrack]);
  2140.             load;
  2141.             if gattr.typtr <> nil then
  2142.               if gattr.typtr^.form<>scalar then error(113)
  2143.               else if not comptypes(gattr.typtr,intptr) then
  2144.                  gen0t(58(*ord*),gattr.typtr);
  2145.             if lattr.typtr <> nil then
  2146.               with lattr.typtr^ do
  2147.             begin
  2148.               if comptypes(inxtype,gattr.typtr) then
  2149.                 begin
  2150.                   if inxtype <> nil then
  2151.                 begin getbounds(inxtype,lmin,lmax);
  2152.                   if debug then
  2153.                     gen2t(45(*chk*),lmin,lmax,intptr);
  2154.                   if lmin>0 then gen1t(31(*dec*),lmin,intptr)
  2155.                   else if lmin<0 then
  2156.                     gen1t(34(*inc*),-lmin,intptr);
  2157.                   (*or simply gen1(31,lmin)*)
  2158.                 end
  2159.                 end
  2160.               else error(139);
  2161.               with gattr do
  2162.                 begin typtr := aeltype; kind := varbl;
  2163.                   access := indrct; idplmt := 0
  2164.                 end;
  2165.               if gattr.typtr <> nil then
  2166.                 begin
  2167.                   lsize := gattr.typtr^.size;
  2168.                   align(gattr.typtr,lsize);
  2169.                   gen1(36(*ixa*),lsize)
  2170.                 end
  2171.             end
  2172.           until sy <> comma;
  2173.           if sy = rbrack then insymbol else error(12)
  2174.         end (*if sy = lbrack*)
  2175.           else
  2176.     (*.*)   if sy = period then
  2177.           begin
  2178.             with gattr do
  2179.               begin
  2180.             if typtr <> nil then
  2181.               if typtr^.form <> records then
  2182.                 begin error(140); typtr := nil end;
  2183.             insymbol;
  2184.             if sy = ident then
  2185.               begin
  2186.                 if typtr <> nil then
  2187.                   begin searchsection(typtr^.fstfld,lcp);
  2188.                 if lcp = nil then
  2189.                   begin error(152); typtr := nil end
  2190.                 else
  2191.                   with lcp^ do
  2192.                     begin typtr := idtype;
  2193.                       case access of
  2194.                     drct:   dplmt := dplmt + fldaddr;
  2195.                     indrct: idplmt := idplmt + fldaddr;
  2196.                     inxd:   error(400)
  2197.                       end
  2198.                     end
  2199.                   end;
  2200.                 insymbol
  2201.               end (*sy = ident*)
  2202.             else error(2)
  2203.               end (*with gattr*)
  2204.           end (*if sy = period*)
  2205.         else
  2206.     (*^*)     begin
  2207.             if gattr.typtr <> nil then
  2208.               with gattr,typtr^ do
  2209.             if form = pointer then
  2210.               begin load; typtr := eltype;
  2211.                 if debug then gen2t(45(*chk*),1,maxaddr,nilptr);
  2212.                 with gattr do
  2213.                   begin kind := varbl; access := indrct;
  2214.                 idplmt := 0
  2215.                   end
  2216.               end
  2217.             else
  2218.               if form = files then typtr := filtype
  2219.               else error(141);
  2220.             insymbol
  2221.           end;
  2222.           if not (sy in fsys + selectsys) then
  2223.         begin error(6); skip(fsys + selectsys) end
  2224.         end (*while*)
  2225.     end (*selector*) ;
  2226.  
  2227.     procedure call(fsys: setofsys; fcp: ctp);
  2228.       var lkey: 1..15;
  2229.  
  2230.       procedure variable(fsys: setofsys);
  2231.         var lcp: ctp;
  2232.       begin
  2233.         if sy = ident then
  2234.           begin searchid([vars,field],lcp); insymbol end
  2235.         else begin error(2); lcp := uvarptr end;
  2236.         selector(fsys,lcp)
  2237.       end (*variable*) ;
  2238.  
  2239.       procedure getputresetrewrite;
  2240.       begin variable(fsys + [rparent]); loadaddress;
  2241.         if gattr.typtr <> nil then
  2242.           if gattr.typtr^.form <> files then error(116);
  2243.         if lkey <= 2 then gen1(30(*csp*),lkey(*get,put*))
  2244.         else error(399)
  2245.       end (*getputresetrewrite*) ;
  2246.  
  2247.       procedure read;
  2248.         var llev:levrange; laddr:addrrange;
  2249.         lsp : stp;
  2250.       begin
  2251.         llev := 1; laddr := lcaftermarkstack;
  2252.         if sy = lparent then
  2253.           begin insymbol;
  2254.         variable(fsys + [comma,rparent]);
  2255.         lsp := gattr.typtr; test := false;
  2256.         if lsp <> nil then
  2257.           if lsp^.form = files then
  2258.             with gattr, lsp^ do
  2259.               begin
  2260.             if filtype = charptr then
  2261.               begin llev := vlevel; laddr := dplmt end
  2262.             else error(399);
  2263.             if sy = rparent then
  2264.               begin if lkey = 5 then error(116);
  2265.                 test := true
  2266.               end
  2267.             else
  2268.               if sy <> comma then
  2269.                 begin error(116); skip(fsys + [comma,rparent]) end;
  2270.             if sy = comma then
  2271.               begin insymbol; variable(fsys + [comma,rparent])
  2272.               end
  2273.             else test := true
  2274.               end;
  2275.            if not test then
  2276.         repeat loadaddress;
  2277.           gen2(50(*lda*),level-llev,laddr);
  2278.           if gattr.typtr <> nil then
  2279.             if gattr.typtr^.form <= subrange then
  2280.               if comptypes(intptr,gattr.typtr) then
  2281.             gen1(30(*csp*),3(*rdi*))
  2282.               else
  2283.             if comptypes(realptr,gattr.typtr) then
  2284.               gen1(30(*csp*),4(*rdr*))
  2285.             else
  2286.               if comptypes(charptr,gattr.typtr) then
  2287.                 gen1(30(*csp*),5(*rdc*))
  2288.               else error(399)
  2289.             else error(116);
  2290.           test := sy <> comma;
  2291.           if not test then
  2292.             begin insymbol; variable(fsys + [comma,rparent])
  2293.             end
  2294.         until test;
  2295.         if sy = rparent then insymbol else error(4)
  2296.           end
  2297.         else if lkey = 5 then error(116);
  2298.         if lkey = 11 then
  2299.           begin gen2(50(*lda*),level-llev,laddr);
  2300.         gen1(30(*csp*),21(*rln*))
  2301.           end
  2302.       end (*read*) ;
  2303.  
  2304.       procedure write;
  2305.         var lsp: stp; default : boolean; llkey: 1..15;
  2306.         llev:levrange; laddr,len:addrrange;
  2307.       begin llkey := lkey;
  2308.         llev := 1; laddr := lcaftermarkstack + charmax;
  2309.         if sy = lparent then
  2310.         begin insymbol;
  2311.         expression(fsys + [comma,colon,rparent]);
  2312.         lsp := gattr.typtr; test := false;
  2313.         if lsp <> nil then
  2314.           if lsp^.form = files then
  2315.         with gattr, lsp^ do
  2316.           begin
  2317.             if filtype = charptr then
  2318.               begin llev := vlevel; laddr := dplmt end
  2319.             else error(399);
  2320.             if sy = rparent then
  2321.               begin if llkey = 6 then error(116);
  2322.             test := true
  2323.               end
  2324.             else
  2325.               if sy <> comma then
  2326.             begin error(116); skip(fsys+[comma,rparent]) end;
  2327.             if sy = comma then
  2328.               begin insymbol; expression(fsys+[comma,colon,rparent])
  2329.               end
  2330.             else test := true
  2331.           end;
  2332.        if not test then
  2333.         repeat
  2334.           lsp := gattr.typtr;
  2335.           if lsp <> nil then
  2336.         if lsp^.form <= subrange then load else loadaddress;
  2337.           if sy = colon then
  2338.         begin insymbol; expression(fsys + [comma,colon,rparent]);
  2339.           if gattr.typtr <> nil then
  2340.             if gattr.typtr <> intptr then error(116);
  2341.           load; default := false
  2342.         end
  2343.           else default := true;
  2344.           if sy = colon then
  2345.         begin insymbol; expression(fsys + [comma,rparent]);
  2346.           if gattr.typtr <> nil then
  2347.             if gattr.typtr <> intptr then error(116);
  2348.           if lsp <> realptr then error(124);
  2349.           load; error(399);
  2350.         end
  2351.           else
  2352.         if lsp = intptr then
  2353.           begin if default then gen2(51(*ldc*),1,10);
  2354.             gen2(50(*lda*),level-llev,laddr);
  2355.             gen1(30(*csp*),6(*wri*))
  2356.           end
  2357.         else
  2358.           if lsp = realptr then
  2359.             begin if default then gen2(51(*ldc*),1,20);
  2360.               gen2(50(*lda*),level-llev,laddr);
  2361.               gen1(30(*csp*),8(*wrr*))
  2362.             end
  2363.           else
  2364.             if lsp = charptr then
  2365.               begin if default then gen2(51(*ldc*),1,1);
  2366.             gen2(50(*lda*),level-llev,laddr);
  2367.             gen1(30(*csp*),9(*wrc*))
  2368.               end
  2369.             else
  2370.               if lsp <> nil then
  2371.             begin
  2372.               if lsp^.form = scalar then error(399)
  2373.               else
  2374.                 if string(lsp) then
  2375.                   begin len := lsp^.size div charmax;
  2376.                 if default then
  2377.                       gen2(51(*ldc*),1,len);
  2378.                 gen2(51(*ldc*),1,len);
  2379.                 gen2(50(*lda*),level-llev,laddr);
  2380.                 gen1(30(*csp*),10(*wrs*))
  2381.                   end
  2382.                 else error(116)
  2383.             end;
  2384.           test := sy <> comma;
  2385.           if not test then
  2386.         begin insymbol; expression(fsys + [comma,colon,rparent])
  2387.         end
  2388.         until test;
  2389.         if sy = rparent then insymbol else error(4)
  2390.         end
  2391.           else if lkey = 6 then error(116);
  2392.         if llkey = 12 then (*writeln*)
  2393.           begin gen2(50(*lda*),level-llev,laddr);
  2394.         gen1(30(*csp*),22(*wln*))
  2395.           end
  2396.       end (*write*) ;
  2397.  
  2398.       procedure pack;
  2399.         var lsp,lsp1: stp;
  2400.       begin error(399); variable(fsys + [comma,rparent]);
  2401.         lsp := nil; lsp1 := nil;
  2402.         if gattr.typtr <> nil then
  2403.           with gattr.typtr^ do
  2404.         if form = arrays then
  2405.           begin lsp := inxtype; lsp1 := aeltype end
  2406.         else error(116);
  2407.         if sy = comma then insymbol else error(20);
  2408.         expression(fsys + [comma,rparent]);
  2409.         if gattr.typtr <> nil then
  2410.           if gattr.typtr^.form <> scalar then error(116)
  2411.           else
  2412.         if not comptypes(lsp,gattr.typtr) then error(116);
  2413.         if sy = comma then insymbol else error(20);
  2414.         variable(fsys + [rparent]);
  2415.         if gattr.typtr <> nil then
  2416.           with gattr.typtr^ do
  2417.         if form = arrays then
  2418.           begin
  2419.             if not comptypes(aeltype,lsp1)
  2420.               or not comptypes(inxtype,lsp) then
  2421.               error(116)
  2422.           end
  2423.         else error(116)
  2424.       end (*pack*) ;
  2425.  
  2426.       procedure unpack;
  2427.         var lsp,lsp1: stp;
  2428.       begin error(399); variable(fsys + [comma,rparent]);
  2429.         lsp := nil; lsp1 := nil;
  2430.         if gattr.typtr <> nil then
  2431.           with gattr.typtr^ do
  2432.         if form = arrays then
  2433.           begin lsp := inxtype; lsp1 := aeltype end
  2434.         else error(116);
  2435.         if sy = comma then insymbol else error(20);
  2436.         variable(fsys + [comma,rparent]);
  2437.         if gattr.typtr <> nil then
  2438.           with gattr.typtr^ do
  2439.         if form = arrays then
  2440.           begin
  2441.             if not comptypes(aeltype,lsp1)
  2442.               or not comptypes(inxtype,lsp) then
  2443.               error(116)
  2444.           end
  2445.         else error(116);
  2446.         if sy = comma then insymbol else error(20);
  2447.         expression(fsys + [rparent]);
  2448.         if gattr.typtr <> nil then
  2449.           if gattr.typtr^.form <> scalar then error(116)
  2450.           else
  2451.         if not comptypes(lsp,gattr.typtr) then error(116);
  2452.       end (*unpack*) ;
  2453.  
  2454.       procedure new;
  2455.         label 1;
  2456.         var lsp,lsp1: stp; varts: integer;
  2457.         lsize: addrrange; lval: valu;
  2458.       begin variable(fsys + [comma,rparent]); loadaddress;
  2459.         lsp := nil; varts := 0; lsize := 0;
  2460.         if gattr.typtr <> nil then
  2461.           with gattr.typtr^ do
  2462.         if form = pointer then
  2463.           begin
  2464.             if eltype <> nil then
  2465.               begin lsize := eltype^.size;
  2466.             if eltype^.form = records then lsp := eltype^.recvar
  2467.               end
  2468.           end
  2469.         else error(116);
  2470.         while sy = comma do
  2471.           begin insymbol;constant(fsys + [comma,rparent],lsp1,lval);
  2472.         varts := varts + 1;
  2473.         (*check to insert here: is constant in tagfieldtype range*)
  2474.         if lsp = nil then error(158)
  2475.         else
  2476.           if lsp^.form <> tagfld then error(162)
  2477.           else
  2478.             if lsp^.tagfieldp <> nil then
  2479.               if string(lsp1) or (lsp1 = realptr) then error(159)
  2480.               else
  2481.             if comptypes(lsp^.tagfieldp^.idtype,lsp1) then
  2482.               begin
  2483.                 lsp1 := lsp^.fstvar;
  2484.                 while lsp1 <> nil do
  2485.                   with lsp1^ do
  2486.                 if varval.ival = lval.ival then
  2487.                   begin lsize := size; lsp := subvar;
  2488.                     goto 1
  2489.                   end
  2490.                 else lsp1 := nxtvar;
  2491.                 lsize := lsp^.size; lsp := nil;
  2492.               end
  2493.             else error(116);
  2494.       1:  end (*while*) ;
  2495.         gen2(51(*ldc*),1,lsize);
  2496.         gen1(30(*csp*),12(*new*));
  2497.       end (*new*) ;
  2498.  
  2499.       procedure mark;
  2500.       begin variable(fsys+[rparent]);
  2501.          if gattr.typtr <> nil then
  2502.            if gattr.typtr^.form = pointer then
  2503.          begin loadaddress; gen1(30(*csp*),23(*sav*)) end
  2504.            else error(116)
  2505.       end(*mark*);
  2506.  
  2507.       procedure release;
  2508.       begin variable(fsys+[rparent]);
  2509.         if gattr.typtr <> nil then
  2510.            if gattr.typtr^.form = pointer then
  2511.               begin load; gen1(30(*csp*),13(*rst*)) end
  2512.            else error(116)
  2513.       end (*release*);
  2514.  
  2515.  
  2516.  
  2517.       procedure abs;
  2518.       begin
  2519.         if gattr.typtr <> nil then
  2520.           if gattr.typtr = intptr then gen0(0(*abi*))
  2521.           else
  2522.         if gattr.typtr = realptr then gen0(1(*abr*))
  2523.         else begin error(125); gattr.typtr := intptr end
  2524.       end (*abs*) ;
  2525.  
  2526.       procedure sqr;
  2527.       begin
  2528.         if gattr.typtr <> nil then
  2529.           if gattr.typtr = intptr then gen0(24(*sqi*))
  2530.           else
  2531.         if gattr.typtr = realptr then gen0(25(*sqr*))
  2532.         else begin error(125); gattr.typtr := intptr end
  2533.       end (*sqr*) ;
  2534.  
  2535.       procedure trunc;
  2536.       begin
  2537.         if gattr.typtr <> nil then
  2538.           if gattr.typtr <> realptr then error(125);
  2539.         gen0(27(*trc*));
  2540.         gattr.typtr := intptr
  2541.       end (*trunc*) ;
  2542.  
  2543.       procedure odd;
  2544.       begin
  2545.         if gattr.typtr <> nil then
  2546.           if gattr.typtr <> intptr then error(125);
  2547.         gen0(20(*odd*));
  2548.         gattr.typtr := boolptr
  2549.       end (*odd*) ;
  2550.  
  2551.       procedure ord;
  2552.       begin
  2553.         if gattr.typtr <> nil then
  2554.           if gattr.typtr^.form >= power then error(125);
  2555.         gen0t(58(*ord*),gattr.typtr);
  2556.         gattr.typtr := intptr
  2557.       end (*ord*) ;
  2558.  
  2559.       procedure chr;
  2560.       begin
  2561.         if gattr.typtr <> nil then
  2562.           if gattr.typtr <> intptr then error(125);
  2563.         gen0(59(*chr*));
  2564.         gattr.typtr := charptr
  2565.       end (*chr*) ;
  2566.  
  2567.       procedure predsucc;
  2568.       begin
  2569.         if gattr.typtr <> nil then
  2570.           if gattr.typtr^.form <> scalar then error(125);
  2571.         if lkey = 7 then gen1t(31(*dec*),1,gattr.typtr)
  2572.         else gen1t(34(*inc*),1,gattr.typtr)
  2573.       end (*predsucc*) ;
  2574.  
  2575.       procedure eof;
  2576.       begin
  2577.         if sy = lparent then
  2578.           begin insymbol; variable(fsys + [rparent]);
  2579.         if sy = rparent then insymbol else error(4)
  2580.           end
  2581.         else
  2582.           with gattr do
  2583.         begin typtr := textptr; kind := varbl; access := drct;
  2584.           vlevel := 1; dplmt := lcaftermarkstack
  2585.         end;
  2586.         loadaddress;
  2587.         if gattr.typtr <> nil then
  2588.           if gattr.typtr^.form <> files then error(125);
  2589.         if lkey = 9 then gen0(8(*eof*)) else gen1(30(*csp*),14(*eln*));
  2590.           gattr.typtr := boolptr
  2591.       end (*eof*) ;
  2592.  
  2593.  
  2594.  
  2595.       procedure callnonstandard;
  2596.         var nxt,lcp: ctp; lsp: stp; lkind: idkind; lb: boolean;
  2597.         locpar, llc: addrrange;
  2598.       begin locpar := 0;
  2599.         with fcp^ do
  2600.           begin nxt := next; lkind := pfkind;
  2601.         if not externl then gen1(41(*mst*),level-pflev)
  2602.           end;
  2603.         if sy = lparent then
  2604.           begin llc := lc;
  2605.         repeat lb := false; (*decide whether proc/func must be passed*)
  2606.           if lkind = actual then
  2607.             begin
  2608.               if nxt = nil then error(126)
  2609.               else lb := nxt^.klass in [proc,func]
  2610.             end else error(399);
  2611.           (*For formal proc/func, lb is false and expression
  2612.            will be called, which will always interpret a proc/func id
  2613.            at its beginning as a call rather than a parameter passing.
  2614.            In this implementation, parameter procedures/functions
  2615.            are therefore not allowed to have procedure/function
  2616.            parameters*)
  2617.           insymbol;
  2618.           if lb then   (*pass function or procedure*)
  2619.             begin error(399);
  2620.               if sy <> ident then
  2621.             begin error(2); skip(fsys + [comma,rparent]) end
  2622.               else
  2623.             begin
  2624.               if nxt^.klass = proc then searchid([proc],lcp)
  2625.               else
  2626.                 begin searchid([func],lcp);
  2627.                   if not comptypes(lcp^.idtype,nxt^.idtype) then
  2628.                 error(128)
  2629.                 end;
  2630.               insymbol;
  2631.               if not (sy in fsys + [comma,rparent]) then
  2632.                 begin error(6); skip(fsys + [comma,rparent]) end
  2633.             end
  2634.             end (*if lb*)
  2635.           else
  2636.             begin expression(fsys + [comma,rparent]);
  2637.               if gattr.typtr <> nil then
  2638.             if lkind = actual then
  2639.               begin
  2640.                 if nxt <> nil then
  2641.                   begin lsp := nxt^.idtype;
  2642.                 if lsp <> nil then
  2643.                   begin
  2644.                     if (nxt^.vkind = actual) then
  2645.                       if lsp^.form <= power then
  2646.                     begin load;
  2647.                       if debug then checkbnds(lsp);
  2648.                       if comptypes(realptr,lsp)
  2649.                          and (gattr.typtr = intptr) then
  2650.                         begin gen0(10(*flt*));
  2651.                           gattr.typtr := realptr
  2652.                         end;
  2653.                       locpar := locpar+lsp^.size;
  2654.                       align(parmptr,locpar);
  2655.                     end
  2656.                       else
  2657.                     begin
  2658.                       loadaddress;
  2659.                       locpar := locpar+ptrsize;
  2660.                       align(parmptr,locpar)
  2661.                     end
  2662.                     else
  2663.                       if gattr.kind = varbl then
  2664.                     begin loadaddress;
  2665.                       locpar := locpar+ptrsize;
  2666.                       align(parmptr,locpar);
  2667.                     end
  2668.                       else error(154);
  2669.                     if not comptypes(lsp,gattr.typtr) then
  2670.                       error(142)
  2671.                   end
  2672.                   end
  2673.               end
  2674.               else (*lkind = formal*)
  2675.             begin (*pass formal param*)
  2676.             end
  2677.             end;
  2678.           if (lkind = actual) and (nxt <> nil) then nxt := nxt^.next
  2679.         until sy <> comma;
  2680.         lc := llc;
  2681.         if sy = rparent then insymbol else error(4)
  2682.           end (*if lparent*);
  2683.         if lkind = actual then
  2684.           begin if nxt <> nil then error(126);
  2685.         with fcp^ do
  2686.           begin
  2687.             if externl then gen1(30(*csp*),pfname)
  2688.             else gencupent(46(*cup*),locpar,pfname);
  2689.           end
  2690.           end;
  2691.         gattr.typtr := fcp^.idtype
  2692.       end (*callnonstandard*) ;
  2693.  
  2694.     begin (*call*)
  2695.       if fcp^.pfdeckind = standard then
  2696.         begin lkey := fcp^.key;
  2697.           if fcp^.klass = proc then
  2698.            begin
  2699.         if not(lkey in [5,6,11,12]) then
  2700.           if sy = lparent then insymbol else error(9);
  2701.         case lkey of
  2702.           1,2,
  2703.           3,4:  getputresetrewrite;
  2704.           5,11: read;
  2705.           6,12: write;
  2706.           7:    pack;
  2707.           8:    unpack;
  2708.           9:    new;
  2709.           10:   release;
  2710.           13:   mark
  2711.         end;
  2712.         if not(lkey in [5,6,11,12]) then
  2713.           if sy = rparent then insymbol else error(4)
  2714.            end
  2715.           else
  2716.         begin
  2717.           if lkey <= 8 then
  2718.             begin
  2719.               if sy = lparent then insymbol else error(9);
  2720.               expression(fsys+[rparent]); load
  2721.             end;
  2722.           case lkey of
  2723.             1:    abs;
  2724.             2:    sqr;
  2725.             3:    trunc;
  2726.             4:    odd;
  2727.             5:    ord;
  2728.             6:    chr;
  2729.             7,8:  predsucc;
  2730.             9,10: eof
  2731.           end;
  2732.           if lkey <= 8 then
  2733.             if sy = rparent then insymbol else error(4)
  2734.         end;
  2735.         end (*standard procedures and functions*)
  2736.       else callnonstandard
  2737.     end (*call*) ;
  2738.  
  2739.     procedure expression;
  2740.       var lattr: attr; lop: operator; typind: char; lsize: addrrange;
  2741.  
  2742.       procedure simpleexpression(fsys: setofsys);
  2743.         var lattr: attr; lop: operator; signed: boolean;
  2744.  
  2745.         procedure term(fsys: setofsys);
  2746.           var lattr: attr; lop: operator;
  2747.  
  2748.           procedure factor(fsys: setofsys);
  2749.         var lcp: ctp; lvp: csp; varpart: boolean;
  2750.             cstpart: setty; lsp: stp;
  2751.           begin
  2752.         if not (sy in facbegsys) then
  2753.           begin error(58); skip(fsys + facbegsys);
  2754.             gattr.typtr := nil
  2755.           end;
  2756.         while sy in facbegsys do
  2757.           begin
  2758.             case sy of
  2759.           (*id*)    ident:
  2760.             begin searchid([konst,vars,field,func],lcp);
  2761.               insymbol;
  2762.               if lcp^.klass = func then
  2763.                 begin call(fsys,lcp);
  2764.                   with gattr do
  2765.                 begin kind := expr;
  2766.                   if typtr <> nil then
  2767.                     if typtr^.form=subrange then
  2768.                       typtr := typtr^.rangetype
  2769.                 end
  2770.                 end
  2771.               else
  2772.                 if lcp^.klass = konst then
  2773.                   with gattr, lcp^ do
  2774.                 begin typtr := idtype; kind := cst;
  2775.                   cval := values
  2776.                 end
  2777.                 else
  2778.                   begin selector(fsys,lcp);
  2779.                 if gattr.typtr<>nil then(*elim.subr.types to*)
  2780.                   with gattr,typtr^ do(*simplify later tests*)
  2781.                     if form = subrange then
  2782.                       typtr := rangetype
  2783.                   end
  2784.             end;
  2785.           (*cst*)   intconst:
  2786.             begin
  2787.               with gattr do
  2788.                 begin typtr := intptr; kind := cst;
  2789.                   cval := val
  2790.                 end;
  2791.               insymbol
  2792.             end;
  2793.               realconst:
  2794.             begin
  2795.               with gattr do
  2796.                 begin typtr := realptr; kind := cst;
  2797.                   cval := val
  2798.                 end;
  2799.               insymbol
  2800.             end;
  2801.               stringconst:
  2802.             begin
  2803.               with gattr do
  2804.                 begin
  2805.                   if lgth = 1 then typtr := charptr
  2806.                   else
  2807.                 begin new(lsp,arrays);
  2808.                   with lsp^ do
  2809.                     begin aeltype := charptr; form:=arrays;
  2810.                       inxtype := nil; size := lgth*charsize
  2811.                     end;
  2812.                   typtr := lsp
  2813.                 end;
  2814.                   kind := cst; cval := val
  2815.                 end;
  2816.               insymbol
  2817.             end;
  2818.           (* ( *)   lparent:
  2819.             begin insymbol; expression(fsys + [rparent]);
  2820.               if sy = rparent then insymbol else error(4)
  2821.             end;
  2822.           (*not*)   notsy:
  2823.             begin insymbol; factor(fsys);
  2824.               load; gen0(19(*not*));
  2825.               if gattr.typtr <> nil then
  2826.                 if gattr.typtr <> boolptr then
  2827.                   begin error(135); gattr.typtr := nil end;
  2828.             end;
  2829.           (*[*)     lbrack:
  2830.             begin insymbol; cstpart := [ ]; varpart := false;
  2831.               new(lsp,power);
  2832.               with lsp^ do
  2833.                 begin elset:=nil;size:=setsize;form:=power end;
  2834.               if sy = rbrack then
  2835.                 begin
  2836.                   with gattr do
  2837.                 begin typtr := lsp; kind := cst end;
  2838.                   insymbol
  2839.                 end
  2840.               else
  2841.                 begin
  2842.                   repeat expression(fsys + [comma,rbrack]);
  2843.                 if gattr.typtr <> nil then
  2844.                   if gattr.typtr^.form <> scalar then
  2845.                     begin error(136); gattr.typtr := nil end
  2846.                   else
  2847.                     if comptypes(lsp^.elset,gattr.typtr) then
  2848.                       begin
  2849.                     if gattr.kind = cst then
  2850.                       if (gattr.cval.ival < setlow) or
  2851.                         (gattr.cval.ival > sethigh) then
  2852.                         error(304)
  2853.                       else
  2854.                         cstpart := cstpart+[gattr.cval.ival]
  2855.                     else
  2856.                       begin load;
  2857.                         if not comptypes(gattr.typtr,intptr)
  2858.                         then gen0t(58(*ord*),gattr.typtr);
  2859.                         gen0(23(*sgs*));
  2860.                         if varpart then gen0(28(*uni*))
  2861.                         else varpart := true
  2862.                       end;
  2863.                     lsp^.elset := gattr.typtr;
  2864.                     gattr.typtr := lsp
  2865.                       end
  2866.                     else error(137);
  2867.                 test := sy <> comma;
  2868.                 if not test then insymbol
  2869.                   until test;
  2870.                   if sy = rbrack then insymbol else error(12)
  2871.                 end;
  2872.               if varpart then
  2873.                 begin
  2874.                   if cstpart <> [ ] then
  2875.                 begin new(lvp,pset); lvp^.pval := cstpart;
  2876.                   lvp^.cclass := pset;
  2877.                   if cstptrix = cstoccmax then error(254)
  2878.                   else
  2879.                     begin cstptrix := cstptrix + 1;
  2880.                       cstptr[cstptrix] := lvp;
  2881.                       gen2(51(*ldc*),5,cstptrix);
  2882.                       gen0(28(*uni*)); gattr.kind := expr
  2883.                     end
  2884.                 end
  2885.                 end
  2886.               else
  2887.                 begin new(lvp,pset); lvp^.pval := cstpart;
  2888.                   lvp^.cclass := pset;
  2889.                   gattr.cval.valp := lvp
  2890.                 end
  2891.             end
  2892.             end (*case*) ;
  2893.             if not (sy in fsys) then
  2894.               begin error(6); skip(fsys + facbegsys) end
  2895.           end (*while*)
  2896.           end (*factor*) ;
  2897.  
  2898.         begin (*term*)
  2899.           factor(fsys + [mulop]);
  2900.           while sy = mulop do
  2901.         begin load; lattr := gattr; lop := op;
  2902.           insymbol; factor(fsys + [mulop]); load;
  2903.           if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
  2904.             case lop of
  2905.         (***)     mul:  if (lattr.typtr=intptr)and(gattr.typtr=intptr)
  2906.                 then gen0(15(*mpi*))
  2907.                 else
  2908.                   begin
  2909.                 if lattr.typtr = intptr then
  2910.                   begin gen0(9(*flo*));
  2911.                     lattr.typtr := realptr
  2912.                   end
  2913.                 else
  2914.                   if gattr.typtr = intptr then
  2915.                     begin gen0(10(*flt*));
  2916.                       gattr.typtr := realptr
  2917.                     end;
  2918.                 if (lattr.typtr = realptr)
  2919.                   and(gattr.typtr=realptr)then gen0(16(*mpr*))
  2920.                 else
  2921.                   if(lattr.typtr^.form=power)
  2922.                     and comptypes(lattr.typtr,gattr.typtr)then
  2923.                     gen0(12(*int*))
  2924.                   else begin error(134); gattr.typtr:=nil end
  2925.                   end;
  2926.         (* / *)   rdiv: begin
  2927.                   if gattr.typtr = intptr then
  2928.                 begin gen0(10(*flt*));
  2929.                   gattr.typtr := realptr
  2930.                 end;
  2931.                   if lattr.typtr = intptr then
  2932.                 begin gen0(9(*flo*));
  2933.                   lattr.typtr := realptr
  2934.                 end;
  2935.                   if (lattr.typtr = realptr)
  2936.                 and (gattr.typtr=realptr)then gen0(7(*dvr*))
  2937.                   else begin error(134); gattr.typtr := nil end
  2938.                 end;
  2939.         (*div*)   idiv: if (lattr.typtr = intptr)
  2940.                   and (gattr.typtr = intptr) then gen0(6(*dvi*))
  2941.                 else begin error(134); gattr.typtr := nil end;
  2942.         (*mod*)   imod: if (lattr.typtr = intptr)
  2943.                   and (gattr.typtr = intptr) then gen0(14(*mod*))
  2944.                 else begin error(134); gattr.typtr := nil end;
  2945.         (*and*)   andop:if (lattr.typtr = boolptr)
  2946.                   and (gattr.typtr = boolptr) then gen0(4(*and*))
  2947.                 else begin error(134); gattr.typtr := nil end
  2948.             end (*case*)
  2949.           else gattr.typtr := nil
  2950.         end (*while*)
  2951.         end (*term*) ;
  2952.  
  2953.       begin (*simpleexpression*)
  2954.         signed := false;
  2955.         if (sy = addop) and (op in [plus,minus]) then
  2956.           begin signed := op = minus; insymbol end;
  2957.         term(fsys + [addop]);
  2958.         if signed then
  2959.           begin load;
  2960.         if gattr.typtr = intptr then gen0(17(*ngi*))
  2961.         else
  2962.           if gattr.typtr = realptr then gen0(18(*ngr*))
  2963.           else begin error(134); gattr.typtr := nil end
  2964.           end;
  2965.         while sy = addop do
  2966.           begin load; lattr := gattr; lop := op;
  2967.         insymbol; term(fsys + [addop]); load;
  2968.         if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
  2969.           case lop of
  2970.       (*+*)       plus:
  2971.               if (lattr.typtr = intptr)and(gattr.typtr = intptr) then
  2972.             gen0(2(*adi*))
  2973.               else
  2974.             begin
  2975.               if lattr.typtr = intptr then
  2976.                 begin gen0(9(*flo*));
  2977.                   lattr.typtr := realptr
  2978.                 end
  2979.               else
  2980.                 if gattr.typtr = intptr then
  2981.                   begin gen0(10(*flt*));
  2982.                 gattr.typtr := realptr
  2983.                   end;
  2984.               if (lattr.typtr = realptr)and(gattr.typtr = realptr)
  2985.                 then gen0(3(*adr*))
  2986.               else if(lattr.typtr^.form=power)
  2987.                  and comptypes(lattr.typtr,gattr.typtr) then
  2988.                  gen0(28(*uni*))
  2989.                    else begin error(134); gattr.typtr:=nil end
  2990.             end;
  2991.       (*-*)       minus:
  2992.               if (lattr.typtr = intptr)and(gattr.typtr = intptr) then
  2993.             gen0(21(*sbi*))
  2994.               else
  2995.             begin
  2996.               if lattr.typtr = intptr then
  2997.                 begin gen0(9(*flo*));
  2998.                   lattr.typtr := realptr
  2999.                 end
  3000.               else
  3001.                 if gattr.typtr = intptr then
  3002.                   begin gen0(10(*flt*));
  3003.                 gattr.typtr := realptr
  3004.                   end;
  3005.               if (lattr.typtr = realptr)and(gattr.typtr = realptr)
  3006.                 then gen0(22(*sbr*))
  3007.               else
  3008.                 if (lattr.typtr^.form = power)
  3009.                   and comptypes(lattr.typtr,gattr.typtr) then
  3010.                   gen0(5(*dif*))
  3011.                 else begin error(134); gattr.typtr := nil end
  3012.             end;
  3013.       (*or*)      orop:
  3014.               if(lattr.typtr=boolptr)and(gattr.typtr=boolptr)then
  3015.             gen0(13(*ior*))
  3016.               else begin error(134); gattr.typtr := nil end
  3017.           end (*case*)
  3018.         else gattr.typtr := nil
  3019.           end (*while*)
  3020.       end (*simpleexpression*) ;
  3021.  
  3022.     begin (*expression*)
  3023.       simpleexpression(fsys + [relop]);
  3024.       if sy = relop then
  3025.         begin
  3026.           if gattr.typtr <> nil then
  3027.         if gattr.typtr^.form <= power then load
  3028.         else loadaddress;
  3029.           lattr := gattr; lop := op;
  3030.           if lop = inop then
  3031.         if not comptypes(gattr.typtr,intptr) then
  3032.           gen0t(58(*ord*),gattr.typtr);
  3033.           insymbol; simpleexpression(fsys);
  3034.           if gattr.typtr <> nil then
  3035.         if gattr.typtr^.form <= power then load
  3036.         else loadaddress;
  3037.           if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
  3038.         if lop = inop then
  3039.           if gattr.typtr^.form = power then
  3040.             if comptypes(lattr.typtr,gattr.typtr^.elset) then
  3041.               gen0(11(*inn*))
  3042.             else begin error(129); gattr.typtr := nil end
  3043.           else begin error(130); gattr.typtr := nil end
  3044.         else
  3045.           begin
  3046.             if lattr.typtr <> gattr.typtr then
  3047.               if lattr.typtr = intptr then
  3048.             begin gen0(9(*flo*));
  3049.               lattr.typtr := realptr
  3050.             end
  3051.               else
  3052.             if gattr.typtr = intptr then
  3053.               begin gen0(10(*flt*));
  3054.                 gattr.typtr := realptr
  3055.               end;
  3056.             if comptypes(lattr.typtr,gattr.typtr) then
  3057.               begin lsize := lattr.typtr^.size;
  3058.             case lattr.typtr^.form of
  3059.               scalar:
  3060.                 if lattr.typtr = realptr then typind := 'r'
  3061.                 else
  3062.                   if lattr.typtr = boolptr then typind := 'b'
  3063.                   else
  3064.                 if lattr.typtr = charptr then typind := 'c'
  3065.                 else typind := 'i';
  3066.               pointer:
  3067.                 begin
  3068.                   if lop in [ltop,leop,gtop,geop] then error(131);
  3069.                   typind := 'a'
  3070.                 end;
  3071.               power:
  3072.                 begin if lop in [ltop,gtop] then error(132);
  3073.                   typind := 's'
  3074.                 end;
  3075.               arrays:
  3076.                 begin
  3077.                   if not string(lattr.typtr)
  3078.                 then error(134);
  3079.                   typind := 'm'
  3080.                 end;
  3081.               records:
  3082.                 begin
  3083.                   error(134);
  3084.                   typind := 'm'
  3085.                 end;
  3086.               files:
  3087.                 begin error(133); typind := 'f' end
  3088.             end;
  3089.             case lop of
  3090.               ltop: gen2(53(*les*),ord(typind),lsize);
  3091.               leop: gen2(52(*leq*),ord(typind),lsize);
  3092.               gtop: gen2(49(*grt*),ord(typind),lsize);
  3093.               geop: gen2(48(*geq*),ord(typind),lsize);
  3094.               neop: gen2(55(*neq*),ord(typind),lsize);
  3095.               eqop: gen2(47(*equ*),ord(typind),lsize)
  3096.             end
  3097.               end
  3098.             else error(129)
  3099.           end;
  3100.           gattr.typtr := boolptr; gattr.kind := expr
  3101.         end (*sy = relop*)
  3102.     end (*expression*) ;
  3103.  
  3104.     procedure assignment(fcp: ctp);
  3105.       var lattr: attr;
  3106.     begin selector(fsys + [becomes],fcp);
  3107.       if sy = becomes then
  3108.         begin
  3109.           if gattr.typtr <> nil then
  3110.         if (gattr.access<>drct) or (gattr.typtr^.form>power) then
  3111.           loadaddress;
  3112.           lattr := gattr;
  3113.           insymbol; expression(fsys);
  3114.           if gattr.typtr <> nil then
  3115.         if gattr.typtr^.form <= power then load
  3116.         else loadaddress;
  3117.           if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
  3118.         begin
  3119.           if comptypes(realptr,lattr.typtr)and(gattr.typtr=intptr)then
  3120.             begin gen0(10(*flt*));
  3121.               gattr.typtr := realptr
  3122.             end;
  3123.           if comptypes(lattr.typtr,gattr.typtr) then
  3124.             case lattr.typtr^.form of
  3125.               scalar,
  3126.               subrange: begin
  3127.                   if debug then checkbnds(lattr.typtr);
  3128.                   store(lattr)
  3129.                 end;
  3130.               pointer: begin
  3131.                  if debug then
  3132.                    gen2t(45(*chk*),0,maxaddr,nilptr);
  3133.                  store(lattr)
  3134.                    end;
  3135.               power:   store(lattr);
  3136.               arrays,
  3137.               records: gen1(40(*mov*),lattr.typtr^.size);
  3138.               files: error(146)
  3139.             end
  3140.           else error(129)
  3141.         end
  3142.         end (*sy = becomes*)
  3143.       else error(51)
  3144.     end (*assignment*) ;
  3145.  
  3146.     procedure gotostatement;
  3147.       var llp: lbp; found: boolean; ttop,ttop1: disprange;
  3148.     begin
  3149.       if sy = intconst then
  3150.         begin
  3151.           found := false;
  3152.           ttop := top;
  3153.           while display[ttop].occur <> blck do ttop := ttop - 1;
  3154.           ttop1 := ttop;
  3155.           repeat
  3156.         llp := display[ttop].flabel;
  3157.         while (llp <> nil) and not found do
  3158.           with llp^ do
  3159.             if labval = val.ival then
  3160.               begin found := true;
  3161.             if ttop = ttop1 then
  3162.               genujpxjp(57(*ujp*),labname)
  3163.             else (*goto leads out of procedure*) error(399)
  3164.               end
  3165.             else llp := nextlab;
  3166.         ttop := ttop - 1
  3167.           until found or (ttop = 0);
  3168.           if not found then error(167);
  3169.           insymbol
  3170.         end
  3171.       else error(15)
  3172.     end (*gotostatement*) ;
  3173.  
  3174.     procedure compoundstatement;
  3175.     begin
  3176.       repeat
  3177.         repeat statement(fsys + [semicolon,endsy])
  3178.         until not (sy in statbegsys);
  3179.         test := sy <> semicolon;
  3180.         if not test then insymbol
  3181.       until test;
  3182.       if sy = endsy then insymbol else error(13)
  3183.     end (*compoundstatemenet*) ;
  3184.  
  3185.     procedure ifstatement;
  3186.       var lcix1,lcix2: integer;
  3187.     begin expression(fsys + [thensy]);
  3188.       genlabel(lcix1); genfjp(lcix1);
  3189.       if sy = thensy then insymbol else error(52);
  3190.       statement(fsys + [elsesy]);
  3191.       if sy = elsesy then
  3192.         begin genlabel(lcix2); genujpxjp(57(*ujp*),lcix2);
  3193.           putlabel(lcix1);
  3194.           insymbol; statement(fsys);
  3195.           putlabel(lcix2)
  3196.         end
  3197.       else putlabel(lcix1)
  3198.     end (*ifstatement*) ;
  3199.  
  3200.     procedure casestatement;
  3201.       label 1;
  3202.       type cip = ^caseinfo;
  3203.            caseinfo = packed
  3204.               record next: cip;
  3205.                 csstart: integer;
  3206.                 cslab: integer
  3207.               end;
  3208.       var lsp,lsp1: stp; fstptr,lpt1,lpt2,lpt3: cip; lval: valu;
  3209.           laddr, lcix, lcix1, lmin, lmax: integer;
  3210.     begin expression(fsys + [ofsy,comma,colon]);
  3211.       load; genlabel(lcix);
  3212.       lsp := gattr.typtr;
  3213.       if lsp <> nil then
  3214.         if (lsp^.form <> scalar) or (lsp = realptr) then
  3215.           begin error(144); lsp := nil end
  3216.         else if not comptypes(lsp,intptr) then gen0t(58(*ord*),lsp);
  3217.       genujpxjp(57(*ujp*),lcix);
  3218.       if sy = ofsy then insymbol else error(8);
  3219.       fstptr := nil; genlabel(laddr);
  3220.       repeat
  3221.         lpt3 := nil; genlabel(lcix1);
  3222.         if not(sy in [semicolon,endsy]) then
  3223.           begin
  3224.         repeat constant(fsys + [comma,colon],lsp1,lval);
  3225.           if lsp <> nil then
  3226.             if comptypes(lsp,lsp1) then
  3227.               begin lpt1 := fstptr; lpt2 := nil;
  3228.             while lpt1 <> nil do
  3229.               with lpt1^ do
  3230.                 begin
  3231.                   if cslab <= lval.ival then
  3232.                 begin if cslab = lval.ival then error(156);
  3233.                   goto 1
  3234.                 end;
  3235.                   lpt2 := lpt1; lpt1 := next
  3236.                 end;
  3237.         1:      new(lpt3);
  3238.             with lpt3^ do
  3239.               begin next := lpt1; cslab := lval.ival;
  3240.                 csstart := lcix1
  3241.               end;
  3242.             if lpt2 = nil then fstptr := lpt3
  3243.             else lpt2^.next := lpt3
  3244.               end
  3245.             else error(147);
  3246.           test := sy <> comma;
  3247.           if not test then insymbol
  3248.         until test;
  3249.         if sy = colon then insymbol else error(5);
  3250.         putlabel(lcix1);
  3251.         repeat statement(fsys + [semicolon])
  3252.         until not (sy in statbegsys);
  3253.         if lpt3 <> nil then
  3254.           genujpxjp(57(*ujp*),laddr);
  3255.           end;
  3256.         test := sy <> semicolon;
  3257.         if not test then insymbol
  3258.       until test;
  3259.       putlabel(lcix);
  3260.       if fstptr <> nil then
  3261.         begin lmax := fstptr^.cslab;
  3262.           (*reverse pointers*)
  3263.           lpt1 := fstptr; fstptr := nil;
  3264.           repeat lpt2 := lpt1^.next; lpt1^.next := fstptr;
  3265.         fstptr := lpt1; lpt1 := lpt2
  3266.           until lpt1 = nil;
  3267.           lmin := fstptr^.cslab;
  3268.           if lmax - lmin < cixmax then
  3269.         begin
  3270.           gen2t(45(*chk*),lmin,lmax,intptr);
  3271.           gen2(51(*ldc*),1,lmin); gen0(21(*sbi*)); genlabel(lcix);
  3272.           genujpxjp(44(*xjp*),lcix); putlabel(lcix);
  3273.           repeat
  3274.             with fstptr^ do
  3275.               begin
  3276.             while cslab > lmin do
  3277.                begin gen0(60(*ujc error*));
  3278.                  lmin := lmin+1
  3279.                end;
  3280.             genujpxjp(57(*ujp*),csstart);
  3281.             fstptr := next; lmin := lmin + 1
  3282.               end
  3283.           until fstptr = nil;
  3284.           putlabel(laddr)
  3285.         end
  3286.           else error(157)
  3287.         end;
  3288.         if sy = endsy then insymbol else error(13)
  3289.     end (*casestatement*) ;
  3290.  
  3291.     procedure repeatstatement;
  3292.       var laddr: integer;
  3293.     begin genlabel(laddr); putlabel(laddr);
  3294.       repeat statement(fsys + [semicolon,untilsy]);
  3295.         if sy in statbegsys then error(14)
  3296.       until not(sy in statbegsys);
  3297.       while sy = semicolon do
  3298.         begin insymbol;
  3299.           repeat statement(fsys + [semicolon,untilsy]);
  3300.         if sy in statbegsys then error(14)
  3301.           until not (sy in statbegsys);
  3302.         end;
  3303.       if sy = untilsy then
  3304.         begin insymbol; expression(fsys); genfjp(laddr)
  3305.         end
  3306.       else error(53)
  3307.     end (*repeatstatement*) ;
  3308.  
  3309.     procedure whilestatement;
  3310.       var laddr, lcix: integer;
  3311.     begin genlabel(laddr); putlabel(laddr);
  3312.       expression(fsys + [dosy]); genlabel(lcix); genfjp(lcix);
  3313.       if sy = dosy then insymbol else error(54);
  3314.       statement(fsys); genujpxjp(57(*ujp*),laddr); putlabel(lcix)
  3315.     end (*whilestatement*) ;
  3316.  
  3317.     procedure forstatement;
  3318.       var lattr: attr;  lsy: symbol;
  3319.           lcix, laddr: integer;
  3320.             llc: addrrange;
  3321.     begin llc := lc;
  3322.       with lattr do
  3323.         begin typtr := nil; kind := varbl;
  3324.           access := drct; vlevel := level; dplmt := 0
  3325.         end;
  3326.       if sy = ident then
  3327.         begin searchid([vars],lcp);
  3328.           with lcp^, lattr do
  3329.         begin typtr := idtype; kind := varbl;
  3330.           if vkind = actual then
  3331.             begin access := drct; vlevel := vlev;
  3332.               dplmt := vaddr
  3333.             end
  3334.           else begin error(155); typtr := nil end
  3335.         end;
  3336.           if lattr.typtr <> nil then
  3337.         if (lattr.typtr^.form > subrange)
  3338.            or comptypes(realptr,lattr.typtr) then
  3339.           begin error(143); lattr.typtr := nil end;
  3340.           insymbol
  3341.         end
  3342.       else
  3343.         begin error(2); skip(fsys + [becomes,tosy,downtosy,dosy]) end;
  3344.       if sy = becomes then
  3345.         begin insymbol; expression(fsys + [tosy,downtosy,dosy]);
  3346.           if gattr.typtr <> nil then
  3347.           if gattr.typtr^.form <> scalar then error(144)
  3348.           else
  3349.             if comptypes(lattr.typtr,gattr.typtr) then
  3350.               begin load; store(lattr) end
  3351.             else error(145)
  3352.         end
  3353.       else
  3354.         begin error(51); skip(fsys + [tosy,downtosy,dosy]) end;
  3355.       if sy in [tosy,downtosy] then
  3356.         begin lsy := sy; insymbol; expression(fsys + [dosy]);
  3357.           if gattr.typtr <> nil then
  3358.           if gattr.typtr^.form <> scalar then error(144)
  3359.         else
  3360.           if comptypes(lattr.typtr,gattr.typtr) then
  3361.             begin load;
  3362.               if not comptypes(lattr.typtr,intptr) then
  3363.             gen0t(58(*ord*),gattr.typtr);
  3364.               align(intptr,lc);
  3365.               gen2t(56(*str*),0,lc,intptr);
  3366.               genlabel(laddr); putlabel(laddr);
  3367.               gattr := lattr; load;
  3368.               if not comptypes(gattr.typtr,intptr) then
  3369.             gen0t(58(*ord*),gattr.typtr);
  3370.               gen2t(54(*lod*),0,lc,intptr);
  3371.               lc := lc + intsize;
  3372.               if lc > lcmax then lcmax := lc;
  3373.               if lsy = tosy then gen2(52(*leq*),ord('i'),1)
  3374.               else gen2(48(*geq*),ord('i'),1);
  3375.             end
  3376.           else error(145)
  3377.         end
  3378.       else begin error(55); skip(fsys + [dosy]) end;
  3379.       genlabel(lcix); genujpxjp(33(*fjp*),lcix);
  3380.       if sy = dosy then insymbol else error(54);
  3381.       statement(fsys);
  3382.       gattr := lattr; load;
  3383.       if lsy=tosy then gen1t(34(*inc*),1,gattr.typtr)
  3384.       else  gen1t(31(*dec*),1,gattr.typtr);
  3385.       store(lattr); genujpxjp(57(*ujp*),laddr); putlabel(lcix);
  3386.       lc := llc;
  3387.     end (*forstatement*) ;
  3388.  
  3389.  
  3390.     procedure withstatement;
  3391.       var lcp: ctp; lcnt1: disprange; llc: addrrange;
  3392.     begin lcnt1 := 0; llc := lc;
  3393.       repeat
  3394.         if sy = ident then
  3395.           begin searchid([vars,field],lcp); insymbol end
  3396.         else begin error(2); lcp := uvarptr end;
  3397.         selector(fsys + [comma,dosy],lcp);
  3398.         if gattr.typtr <> nil then
  3399.           if gattr.typtr^.form = records then
  3400.         if top < displimit then
  3401.           begin top := top + 1; lcnt1 := lcnt1 + 1;
  3402.             with display[top] do
  3403.               begin fname := gattr.typtr^.fstfld;
  3404.             flabel := nil
  3405.               end;
  3406.             if gattr.access = drct then
  3407.               with display[top] do
  3408.             begin occur := crec; clev := gattr.vlevel;
  3409.               cdspl := gattr.dplmt
  3410.             end
  3411.             else
  3412.               begin loadaddress;
  3413.             align(nilptr,lc);
  3414.             gen2t(56(*str*),0,lc,nilptr);
  3415.             with display[top] do
  3416.               begin occur := vrec; vdspl := lc end;
  3417.             lc := lc+ptrsize;
  3418.             if lc > lcmax then lcmax := lc
  3419.               end
  3420.           end
  3421.         else error(250)
  3422.           else error(140);
  3423.         test := sy <> comma;
  3424.         if not test then insymbol
  3425.       until test;
  3426.       if sy = dosy then insymbol else error(54);
  3427.       statement(fsys);
  3428.       top := top-lcnt1; lc := llc;
  3429.     end (*withstatement*) ;
  3430.  
  3431.       begin (*statement*)
  3432.     if sy = intconst then (*label*)
  3433.       begin llp := display[level].flabel;
  3434.         while llp <> nil do
  3435.           with llp^ do
  3436.         if labval = val.ival then
  3437.           begin if defined then error(165);
  3438.             putlabel(labname); defined := true;
  3439.             goto 1
  3440.           end
  3441.         else llp := nextlab;
  3442.         error(167);
  3443.       1:    insymbol;
  3444.         if sy = colon then insymbol else error(5)
  3445.       end;
  3446.     if not (sy in fsys + [ident]) then
  3447.       begin error(6); skip(fsys) end;
  3448.     if sy in statbegsys + [ident] then
  3449.       begin
  3450.         case sy of
  3451.           ident:    begin searchid([vars,field,func,proc],lcp); insymbol;
  3452.               if lcp^.klass = proc then call(fsys,lcp)
  3453.               else assignment(lcp)
  3454.             end;
  3455.           beginsy:  begin insymbol; compoundstatement end;
  3456.           gotosy:   begin insymbol; gotostatement end;
  3457.           ifsy:     begin insymbol; ifstatement end;
  3458.           casesy:   begin insymbol; casestatement end;
  3459.           whilesy:  begin insymbol; whilestatement end;
  3460.           repeatsy: begin insymbol; repeatstatement end;
  3461.           forsy:    begin insymbol; forstatement end;
  3462.           withsy:   begin insymbol; withstatement end
  3463.         end;
  3464.         if not (sy in [semicolon,endsy,elsesy,untilsy]) then
  3465.           begin error(6); skip(fsys) end
  3466.       end
  3467.       end (*statement*) ;
  3468.  
  3469.     begin (*body*)
  3470.       if fprocp <> nil then entname := fprocp^.pfname
  3471.       else genlabel(entname);
  3472.       cstptrix := 0; topnew := lcaftermarkstack; topmax := lcaftermarkstack;
  3473.       putlabel(entname); genlabel(segsize); genlabel(stacktop);
  3474.       gencupent(32(*ent1*),1,segsize); gencupent(32(*ent2*),2,stacktop);
  3475.       if fprocp <> nil then (*copy multiple values into local cells*)
  3476.     begin llc1 := lcaftermarkstack;
  3477.       lcp := fprocp^.next;
  3478.       while lcp <> nil do
  3479.         with lcp^ do
  3480.           begin
  3481.         align(parmptr,llc1);
  3482.         if klass = vars then
  3483.           if idtype <> nil then
  3484.             if idtype^.form > power then
  3485.               begin
  3486.             if vkind = actual then
  3487.               begin
  3488.                 gen2(50(*lda*),0,vaddr);
  3489.                 gen2t(54(*lod*),0,llc1,nilptr);
  3490.                 gen1(40(*mov*),idtype^.size);
  3491.               end;
  3492.             llc1 := llc1 + ptrsize
  3493.               end
  3494.             else llc1 := llc1 + idtype^.size;
  3495.         lcp := lcp^.next;
  3496.           end;
  3497.     end;
  3498.       lcmax := lc;
  3499.       repeat
  3500.     repeat statement(fsys + [semicolon,endsy])
  3501.     until not (sy in statbegsys);
  3502.     test := sy <> semicolon;
  3503.     if not test then insymbol
  3504.       until test;
  3505.       if sy = endsy then insymbol else error(13);
  3506.       llp := display[top].flabel; (*test for undefined labels*)
  3507.       while llp <> nil do
  3508.     with llp^ do
  3509.       begin
  3510.         if not defined then
  3511.           begin error(168);
  3512.         writeln(output); writeln(output,' label ',labval);
  3513.         write(output,' ':chcnt+16)
  3514.           end;
  3515.         llp := nextlab
  3516.       end;
  3517.       if fprocp <> nil then
  3518.     begin
  3519.       if fprocp^.idtype = nil then gen1(42(*ret*),ord('p'))
  3520.       else gen0t(42(*ret*),fprocp^.idtype);
  3521.       align(parmptr,lcmax);
  3522.       if prcode then
  3523.         begin writeln(prr,'l',segsize:4,'=',lcmax);
  3524.           writeln(prr,'l',stacktop:4,'=',topmax)
  3525.         end
  3526.     end
  3527.       else
  3528.     begin gen1(42(*ret*),ord('p'));
  3529.       align(parmptr,lcmax);
  3530.       if prcode then
  3531.         begin writeln(prr,'l',segsize:4,'=',lcmax);
  3532.           writeln(prr,'l',stacktop:4,'=',topmax);
  3533.           writeln(prr,'q')
  3534.         end;
  3535.       ic := 0;
  3536.       (*generate call of main program; note that this call must be loaded
  3537.         at absolute address zero*)
  3538.       gen1(41(*mst*),0); gencupent(46(*cup*),0,entname); gen0(29(*stp*));
  3539.       if prcode then
  3540.         writeln(prr,'q');
  3541.       saveid := id;
  3542.       while fextfilep <> nil do
  3543.         begin
  3544.           with fextfilep^ do
  3545.         if not ((filename = 'input   ') or (filename = 'output  ') or
  3546.             (filename = 'prd     ') or (filename = 'prr     '))
  3547.         then begin id := filename;
  3548.                searchid([vars],llcp);
  3549.                if llcp^.idtype<>nil then
  3550.              if llcp^.idtype^.form<>files then
  3551.                begin writeln(output);
  3552.                  writeln(output,' ':8,'undeclared ','external ',
  3553.                    'file',fextfilep^.filename:8);
  3554.                  write(output,' ':chcnt+16)
  3555.                end
  3556.              end;
  3557.         fextfilep := fextfilep^.nextfile
  3558.         end;
  3559.       id := saveid;
  3560.       if prtables then
  3561.         begin writeln(output); printtables(true)
  3562.         end
  3563.     end;
  3564.     end (*body*) ;
  3565.  
  3566.   begin (*block*)
  3567.     dp := true;
  3568.     repeat
  3569.       if sy = labelsy then
  3570.     begin insymbol; labeldeclaration end;
  3571.       if sy = constsy then
  3572.     begin insymbol; constdeclaration end;
  3573.       if sy = typesy then
  3574.     begin insymbol; typedeclaration end;
  3575.       if sy = varsy then
  3576.     begin insymbol; vardeclaration end;
  3577.       while sy in [procsy,funcsy] do
  3578.     begin lsy := sy; insymbol; procdeclaration(lsy) end;
  3579.       if sy <> beginsy then
  3580.     begin error(18); skip(fsys) end
  3581.     until (sy in statbegsys) or eof(input);
  3582.     dp := false;
  3583.     if sy = beginsy then insymbol else error(17);
  3584.     repeat body(fsys + [casesy]);
  3585.       if sy <> fsy then
  3586.     begin error(6); skip(fsys) end
  3587.     until ((sy = fsy) or (sy in blockbegsys)) or eof(input);
  3588.   end (*block*) ;
  3589.  
  3590.   procedure programme(fsys:setofsys);
  3591.     var extfp:extfilep;
  3592.   begin
  3593.     if sy = progsy then
  3594.       begin insymbol; if sy <> ident then error(2); insymbol;
  3595.     if not (sy in [lparent,semicolon]) then error(14);
  3596.     if sy = lparent  then
  3597.       begin
  3598.         repeat insymbol;
  3599.           if sy = ident then
  3600.         begin new(extfp);
  3601.           with extfp^ do
  3602.             begin filename := id; nextfile := fextfilep end;
  3603.           fextfilep := extfp;
  3604.           insymbol;
  3605.           if not ( sy in [comma,rparent] ) then error(20)
  3606.         end
  3607.           else error(2)
  3608.         until sy <> comma;
  3609.         if sy <> rparent then error(4);
  3610.         insymbol
  3611.       end;
  3612.     if sy <> semicolon then error(14)
  3613.     else insymbol;
  3614.       end;
  3615.     repeat block(fsys,period,nil);
  3616.       if sy <> period then error(21)
  3617.     until (sy = period) or eof(input);
  3618.     if list then writeln(output);
  3619.     if errinx <> 0 then
  3620.       begin list := false; endofline end
  3621.   end (*programme*) ;
  3622.  
  3623.  
  3624.   procedure stdnames;
  3625.   begin
  3626.     na[ 1] := 'false   '; na[ 2] := 'true    '; na[ 3] := 'input   ';
  3627.     na[ 4] := 'output  '; na[ 5] := 'get     '; na[ 6] := 'put     ';
  3628.     na[ 7] := 'reset   '; na[ 8] := 'rewrite '; na[ 9] := 'read    ';
  3629.     na[10] := 'write   '; na[11] := 'pack    '; na[12] := 'unpack  ';
  3630.     na[13] := 'new     '; na[14] := 'release '; na[15] := 'readln  ';
  3631.     na[16] := 'writeln ';
  3632.     na[17] := 'abs     '; na[18] := 'sqr     '; na[19] := 'trunc   ';
  3633.     na[20] := 'odd     '; na[21] := 'ord     '; na[22] := 'chr     ';
  3634.     na[23] := 'pred    '; na[24] := 'succ    '; na[25] := 'eof     ';
  3635.     na[26] := 'eoln    ';
  3636.     na[27] := 'sin     '; na[28] := 'cos     '; na[29] := 'exp     ';
  3637.     na[30] := 'sqrt    '; na[31] := 'ln      '; na[32] := 'arctan  ';
  3638.     na[33] := 'prd     '; na[34] := 'prr     '; na[35] := 'mark    ';
  3639.   end (*stdnames*) ;
  3640.  
  3641.   procedure enterstdtypes;
  3642.  
  3643.   begin                         (*type underlying:*)
  3644.                             (******************)
  3645.  
  3646.     new(intptr,scalar,standard);                  (*integer*)
  3647.     with intptr^ do
  3648.       begin size := intsize; form := scalar; scalkind := standard end;
  3649.     new(realptr,scalar,standard);                 (*real*)
  3650.     with realptr^ do
  3651.       begin size := realsize; form := scalar; scalkind := standard end;
  3652.     new(charptr,scalar,standard);                 (*char*)
  3653.     with charptr^ do
  3654.       begin size := charsize; form := scalar; scalkind := standard end;
  3655.     new(boolptr,scalar,declared);                 (*boolean*)
  3656.     with boolptr^ do
  3657.       begin size := boolsize; form := scalar; scalkind := declared end;
  3658.     new(nilptr,pointer);                      (*nil*)
  3659.     with nilptr^ do
  3660.       begin eltype := nil; size := ptrsize; form := pointer end;
  3661.     new(parmptr,scalar,standard); (*for alignment of parameters*)
  3662.     with parmptr^ do
  3663.       begin size := parmsize; form := scalar; scalkind := standard end ;
  3664.     new(textptr,files);                       (*text*)
  3665.     with textptr^ do
  3666.       begin filtype := charptr; size := charsize; form := files end
  3667.   end (*enterstdtypes*) ;
  3668.  
  3669.   procedure entstdnames;
  3670.     var cp,cp1: ctp; i: integer;
  3671.   begin                               (*name:*)
  3672.                                   (*******)
  3673.  
  3674.     new(cp,types);                        (*integer*)
  3675.     with cp^ do
  3676.       begin name := 'integer '; idtype := intptr; klass := types end;
  3677.     enterid(cp);
  3678.     new(cp,types);                        (*real*)
  3679.     with cp^ do
  3680.       begin name := 'real    '; idtype := realptr; klass := types end;
  3681.     enterid(cp);
  3682.     new(cp,types);                        (*char*)
  3683.     with cp^ do
  3684.       begin name := 'char    '; idtype := charptr; klass := types end;
  3685.     enterid(cp);
  3686.     new(cp,types);                        (*boolean*)
  3687.     with cp^ do
  3688.       begin name := 'boolean '; idtype := boolptr; klass := types end;
  3689.     enterid(cp);
  3690.     cp1 := nil;
  3691.     for i := 1 to 2 do
  3692.       begin new(cp,konst);                    (*false,true*)
  3693.     with cp^ do
  3694.       begin name := na[i]; idtype := boolptr;
  3695.         next := cp1; values.ival := i - 1; klass := konst
  3696.       end;
  3697.     enterid(cp); cp1 := cp
  3698.       end;
  3699.     boolptr^.fconst := cp;
  3700.     new(cp,konst);                        (*nil*)
  3701.     with cp^ do
  3702.       begin name := 'nil     '; idtype := nilptr;
  3703.     next := nil; values.ival := 0; klass := konst
  3704.       end;
  3705.     enterid(cp);
  3706.     for i := 3 to 4 do
  3707.       begin new(cp,vars);                     (*input,output*)
  3708.     with cp^ do
  3709.       begin name := na[i]; idtype := textptr; klass := vars;
  3710.         vkind := actual; next := nil; vlev := 1;
  3711.         vaddr := lcaftermarkstack+(i-3)*charmax;
  3712.       end;
  3713.     enterid(cp)
  3714.       end;
  3715.     for i:=33 to 34 do
  3716.       begin new(cp,vars);                     (*prd,prr files*)
  3717.      with cp^ do
  3718.        begin name := na[i]; idtype := textptr; klass := vars;
  3719.           vkind := actual; next := nil; vlev := 1;
  3720.           vaddr := lcaftermarkstack+(i-31)*charmax;
  3721.        end;
  3722.      enterid(cp)
  3723.       end;
  3724.     for i := 5 to 16 do
  3725.       begin new(cp,proc,standard);                (*get,put,reset*)
  3726.     with cp^ do                       (*rewrite,read*)
  3727.       begin name := na[i]; idtype := nil;         (*write,pack*)
  3728.         next := nil; key := i - 4;            (*unpack,pack*)
  3729.         klass := proc; pfdeckind := standard
  3730.       end;
  3731.     enterid(cp)
  3732.       end;
  3733.     new(cp,proc,standard);
  3734.     with cp^ do
  3735.       begin name:=na[35]; idtype:=nil;
  3736.         next:= nil; key:=13;
  3737.         klass:=proc; pfdeckind:= standard
  3738.       end; enterid(cp);
  3739.     for i := 17 to 26 do
  3740.       begin new(cp,func,standard);                (*abs,sqr,trunc*)
  3741.     with cp^ do                       (*odd,ord,chr*)
  3742.       begin name := na[i]; idtype := nil;         (*pred,succ,eof*)
  3743.         next := nil; key := i - 16;
  3744.         klass := func; pfdeckind := standard
  3745.       end;
  3746.     enterid(cp)
  3747.       end;
  3748.     new(cp,vars);              (*parameter of predeclared functions*)
  3749.     with cp^ do
  3750.       begin name := '        '; idtype := realptr; klass := vars;
  3751.     vkind := actual; next := nil; vlev := 1; vaddr := 0
  3752.       end;
  3753.     for i := 27 to 32 do
  3754.       begin new(cp1,func,declared,actual);            (*sin,cos,exp*)
  3755.     with cp1^ do                      (*sqrt,ln,arctan*)
  3756.       begin name := na[i]; idtype := realptr; next := cp;
  3757.         forwdecl := false; externl := true; pflev := 0; pfname := i - 12;
  3758.         klass := func; pfdeckind := declared; pfkind := actual
  3759.       end;
  3760.     enterid(cp1)
  3761.       end
  3762.   end (*entstdnames*) ;
  3763.  
  3764.   procedure enterundecl;
  3765.   begin
  3766.     new(utypptr,types);
  3767.     with utypptr^ do
  3768.       begin name := '        '; idtype := nil; klass := types end;
  3769.     new(ucstptr,konst);
  3770.     with ucstptr^ do
  3771.       begin name := '        '; idtype := nil; next := nil;
  3772.     values.ival := 0; klass := konst
  3773.       end;
  3774.     new(uvarptr,vars);
  3775.     with uvarptr^ do
  3776.       begin name := '        '; idtype := nil; vkind := actual;
  3777.     next := nil; vlev := 0; vaddr := 0; klass := vars
  3778.       end;
  3779.     new(ufldptr,field);
  3780.     with ufldptr^ do
  3781.       begin name := '        '; idtype := nil; next := nil; fldaddr := 0;
  3782.     klass := field
  3783.       end;
  3784.     new(uprcptr,proc,declared,actual);
  3785.     with uprcptr^ do
  3786.       begin name := '        '; idtype := nil; forwdecl := false;
  3787.     next := nil; externl := false; pflev := 0; genlabel(pfname);
  3788.     klass := proc; pfdeckind := declared; pfkind := actual
  3789.       end;
  3790.     new(ufctptr,func,declared,actual);
  3791.     with ufctptr^ do
  3792.       begin name := '        '; idtype := nil; next := nil;
  3793.     forwdecl := false; externl := false; pflev := 0; genlabel(pfname);
  3794.     klass := func; pfdeckind := declared; pfkind := actual
  3795.       end
  3796.   end (*enterundecl*) ;
  3797.  
  3798.   procedure initscalars;
  3799.   begin fwptr := nil;
  3800.     prtables := false; list := true; prcode := true; debug := true;
  3801.     dp := true; prterr := true; errinx := 0;
  3802.     intlabel := 0; kk := 8; fextfilep := nil;
  3803.     lc := lcaftermarkstack+filebuffer*charmax;
  3804.     (* note in the above reservation of buffer store for 2 text files *)
  3805.     ic := 3; eol := true; linecount := 0;
  3806.     ch := ' '; chcnt := 0;
  3807.     globtestp := nil;
  3808.     mxint10 := maxint div 10; digmax := strglgth - 1;
  3809.   end (*initscalars*) ;
  3810.  
  3811.   procedure initsets;
  3812.   begin
  3813.     constbegsys := [addop,intconst,realconst,stringconst,ident];
  3814.     simptypebegsys := [lparent] + constbegsys;
  3815.     typebegsys:=[arrow,packedsy,arraysy,recordsy,setsy,filesy]+simptypebegsys;
  3816.     typedels := [arraysy,recordsy,setsy,filesy];
  3817.     blockbegsys := [labelsy,constsy,typesy,varsy,procsy,funcsy,beginsy];
  3818.     selectsys := [arrow,period,lbrack];
  3819.     facbegsys := [intconst,realconst,stringconst,ident,lparent,lbrack,notsy];
  3820.     statbegsys := [beginsy,gotosy,ifsy,whilesy,repeatsy,forsy,withsy,casesy];
  3821.   end (*initsets*) ;
  3822.  
  3823.   procedure inittables;
  3824.     procedure reswords;
  3825.     begin
  3826.       rw[ 1] := 'if      '; rw[ 2] := 'do      '; rw[ 3] := 'of      ';
  3827.       rw[ 4] := 'to      '; rw[ 5] := 'in      '; rw[ 6] := 'or      ';
  3828.       rw[ 7] := 'end     '; rw[ 8] := 'for     '; rw[ 9] := 'var     ';
  3829.       rw[10] := 'div     '; rw[11] := 'mod     '; rw[12] := 'set     ';
  3830.       rw[13] := 'and     '; rw[14] := 'not     '; rw[15] := 'then    ';
  3831.       rw[16] := 'else    '; rw[17] := 'with    '; rw[18] := 'goto    ';
  3832.       rw[19] := 'case    '; rw[20] := 'type    ';
  3833.       rw[21] := 'file    '; rw[22] := 'begin   ';
  3834.       rw[23] := 'until   '; rw[24] := 'while   '; rw[25] := 'array   ';
  3835.       rw[26] := 'const   '; rw[27] := 'label   ';
  3836.       rw[28] := 'repeat  '; rw[29] := 'record  '; rw[30] := 'downto  ';
  3837.       rw[31] := 'packed  '; rw[32] := 'forward '; rw[33] := 'program ';
  3838.       rw[34] := 'function'; rw[35] := 'procedur';
  3839.       frw[1] :=  1; frw[2] :=  1; frw[3] :=  7; frw[4] := 15; frw[5] := 22;
  3840.       frw[6] := 28; frw[7] := 32; frw[8] := 34; frw[9] := 36;
  3841.     end (*reswords*) ;
  3842.  
  3843.     procedure symbols;
  3844.     begin
  3845.       rsy[ 1] := ifsy;      rsy[ 2] := dosy;      rsy[ 3] := ofsy;
  3846.       rsy[ 4] := tosy;      rsy[ 5] := relop;     rsy[ 6] := addop;
  3847.       rsy[ 7] := endsy;     rsy[ 8] := forsy;     rsy[ 9] := varsy;
  3848.       rsy[10] := mulop;     rsy[11] := mulop;     rsy[12] := setsy;
  3849.       rsy[13] := mulop;     rsy[14] := notsy;     rsy[15] := thensy;
  3850.       rsy[16] := elsesy;    rsy[17] := withsy;    rsy[18] := gotosy;
  3851.       rsy[19] := casesy;    rsy[20] := typesy;
  3852.       rsy[21] := filesy;    rsy[22] := beginsy;
  3853.       rsy[23] := untilsy;   rsy[24] := whilesy;   rsy[25] := arraysy;
  3854.       rsy[26] := constsy;   rsy[27] := labelsy;
  3855.       rsy[28] := repeatsy;  rsy[29] := recordsy;  rsy[30] := downtosy;
  3856.       rsy[31] := packedsy;  rsy[32] := forwardsy; rsy[33] := progsy;
  3857.       rsy[34] := funcsy;    rsy[35] := procsy;
  3858.       ssy['+'] := addop ;   ssy['-'] := addop;    ssy['*'] := mulop;
  3859.       ssy['/'] := mulop ;   ssy['('] := lparent;  ssy[')'] := rparent;
  3860.       ssy['$'] := othersy ; ssy['='] := relop;    ssy[' '] := othersy;
  3861.       ssy[','] := comma ;   ssy['.'] := period;   ssy['''']:= othersy;
  3862.       ssy['['] := lbrack ;  ssy[']'] := rbrack;   ssy[':'] := colon;
  3863.       ssy['^'] := arrow ;   ssy['<'] := relop;    ssy['>'] := relop;
  3864.       ssy[';'] := semicolon;
  3865.     end (*symbols*) ;
  3866.  
  3867.     procedure rators;
  3868.       var i: integer;
  3869.     begin
  3870.       for i := 1 to 35 (*nr of res words*) do rop[i] := noop;
  3871.       rop[5] := inop; rop[10] := idiv; rop[11] := imod;
  3872.       rop[6] := orop; rop[13] := andop;
  3873.       for i := ordminchar to ordmaxchar do sop[chr(i)] := noop;
  3874.       sop['+'] := plus; sop['-'] := minus; sop['*'] := mul; sop['/'] := rdiv;
  3875.       sop['='] := eqop; sop['<'] := ltop;  sop['>'] := gtop;
  3876.     end (*rators*) ;
  3877.  
  3878.     procedure procmnemonics;
  3879.     begin
  3880.       sna[ 1] :=' get'; sna[ 2] :=' put'; sna[ 3] :=' rdi'; sna[ 4] :=' rdr';
  3881.       sna[ 5] :=' rdc'; sna[ 6] :=' wri'; sna[ 7] :=' wro'; sna[ 8] :=' wrr';
  3882.       sna[ 9] :=' wrc'; sna[10] :=' wrs'; sna[11] :=' pak'; sna[12] :=' new';
  3883.       sna[13] :=' rst'; sna[14] :=' eln'; sna[15] :=' sin'; sna[16] :=' cos';
  3884.       sna[17] :=' exp'; sna[18] :=' sqt'; sna[19] :=' log'; sna[20] :=' atn';
  3885.       sna[21] :=' rln'; sna[22] :=' wln'; sna[23] :=' sav';
  3886.     end (*procmnemonics*) ;
  3887.  
  3888.     procedure instrmnemonics;
  3889.     begin
  3890.       mn[ 0] :=' abi'; mn[ 1] :=' abr'; mn[ 2] :=' adi'; mn[ 3] :=' adr';
  3891.       mn[ 4] :=' and'; mn[ 5] :=' dif'; mn[ 6] :=' dvi'; mn[ 7] :=' dvr';
  3892.       mn[ 8] :=' eof'; mn[ 9] :=' flo'; mn[10] :=' flt'; mn[11] :=' inn';
  3893.       mn[12] :=' int'; mn[13] :=' ior'; mn[14] :=' mod'; mn[15] :=' mpi';
  3894.       mn[16] :=' mpr'; mn[17] :=' ngi'; mn[18] :=' ngr'; mn[19] :=' not';
  3895.       mn[20] :=' odd'; mn[21] :=' sbi'; mn[22] :=' sbr'; mn[23] :=' sgs';
  3896.       mn[24] :=' sqi'; mn[25] :=' sqr'; mn[26] :=' sto'; mn[27] :=' trc';
  3897.       mn[28] :=' uni'; mn[29] :=' stp'; mn[30] :=' csp'; mn[31] :=' dec';
  3898.       mn[32] :=' ent'; mn[33] :=' fjp'; mn[34] :=' inc'; mn[35] :=' ind';
  3899.       mn[36] :=' ixa'; mn[37] :=' lao'; mn[38] :=' lca'; mn[39] :=' ldo';
  3900.       mn[40] :=' mov'; mn[41] :=' mst'; mn[42] :=' ret'; mn[43] :=' sro';
  3901.       mn[44] :=' xjp'; mn[45] :=' chk'; mn[46] :=' cup'; mn[47] :=' equ';
  3902.       mn[48] :=' geq'; mn[49] :=' grt'; mn[50] :=' lda'; mn[51] :=' ldc';
  3903.       mn[52] :=' leq'; mn[53] :=' les'; mn[54] :=' lod'; mn[55] :=' neq';
  3904.       mn[56] :=' str'; mn[57] :=' ujp'; mn[58] :=' ord'; mn[59] :=' chr';
  3905.       mn[60] :=' ujc';
  3906.     end (*instrmnemonics*) ;
  3907.  
  3908.     procedure chartypes;
  3909.     var i : integer;
  3910.     begin
  3911.       for i := ordminchar to ordmaxchar do chartp[chr(i)] := illegal;
  3912.       chartp['a'] := letter  ;
  3913.       chartp['b'] := letter  ; chartp['c'] := letter  ;
  3914.       chartp['d'] := letter  ; chartp['e'] := letter  ;
  3915.       chartp['f'] := letter  ; chartp['g'] := letter  ;
  3916.       chartp['h'] := letter  ; chartp['i'] := letter  ;
  3917.       chartp['j'] := letter  ; chartp['k'] := letter  ;
  3918.       chartp['l'] := letter  ; chartp['m'] := letter  ;
  3919.       chartp['n'] := letter  ; chartp['o'] := letter  ;
  3920.       chartp['p'] := letter  ; chartp['q'] := letter  ;
  3921.       chartp['r'] := letter  ; chartp['s'] := letter  ;
  3922.       chartp['t'] := letter  ; chartp['u'] := letter  ;
  3923.       chartp['v'] := letter  ; chartp['w'] := letter  ;
  3924.       chartp['x'] := letter  ; chartp['y'] := letter  ;
  3925.       chartp['z'] := letter  ; chartp['0'] := number  ;
  3926.       chartp['1'] := number  ; chartp['2'] := number  ;
  3927.       chartp['3'] := number  ; chartp['4'] := number  ;
  3928.       chartp['5'] := number  ; chartp['6'] := number  ;
  3929.       chartp['7'] := number  ; chartp['8'] := number  ;
  3930.       chartp['9'] := number  ; chartp['+'] := special ;
  3931.       chartp['-'] := special ; chartp['*'] := special ;
  3932.       chartp['/'] := special ; chartp['('] := chlparen;
  3933.       chartp[')'] := special ; chartp['$'] := special ;
  3934.       chartp['='] := special ; chartp[' '] := chspace ;
  3935.       chartp[','] := special ; chartp['.'] := chperiod;
  3936.       chartp['''']:= chstrquo; chartp['['] := special ;
  3937.       chartp[']'] := special ; chartp[':'] := chcolon ;
  3938.       chartp['^'] := special ; chartp[';'] := special ;
  3939.       chartp['<'] := chlt    ; chartp['>'] := chgt    ;
  3940.       ordint['0'] := 0; ordint['1'] := 1; ordint['2'] := 2;
  3941.       ordint['3'] := 3; ordint['4'] := 4; ordint['5'] := 5;
  3942.       ordint['6'] := 6; ordint['7'] := 7; ordint['8'] := 8;
  3943.       ordint['9'] := 9;
  3944.     end;
  3945.  
  3946.     procedure initdx;
  3947.     begin
  3948.       cdx[ 0] :=  0; cdx[ 1] :=  0; cdx[ 2] := -1; cdx[ 3] := -1;
  3949.       cdx[ 4] := -1; cdx[ 5] := -1; cdx[ 6] := -1; cdx[ 7] := -1;
  3950.       cdx[ 8] :=  0; cdx[ 9] :=  0; cdx[10] :=  0; cdx[11] := -1;
  3951.       cdx[12] := -1; cdx[13] := -1; cdx[14] := -1; cdx[15] := -1;
  3952.       cdx[16] := -1; cdx[17] :=  0; cdx[18] :=  0; cdx[19] :=  0;
  3953.       cdx[20] :=  0; cdx[21] := -1; cdx[22] := -1; cdx[23] :=  0;
  3954.       cdx[24] :=  0; cdx[25] :=  0; cdx[26] := -2; cdx[27] :=  0;
  3955.       cdx[28] := -1; cdx[29] :=  0; cdx[30] :=  0; cdx[31] :=  0;
  3956.       cdx[32] :=  0; cdx[33] := -1; cdx[34] :=  0; cdx[35] :=  0;
  3957.       cdx[36] := -1; cdx[37] := +1; cdx[38] := +1; cdx[39] := +1;
  3958.       cdx[40] := -2; cdx[41] :=  0; cdx[42] :=  0; cdx[43] := -1;
  3959.       cdx[44] := -1; cdx[45] :=  0; cdx[46] :=  0; cdx[47] := -1;
  3960.       cdx[48] := -1; cdx[49] := -1; cdx[50] := +1; cdx[51] := +1;
  3961.       cdx[52] := -1; cdx[53] := -1; cdx[54] := +1; cdx[55] := -1;
  3962.       cdx[56] := -1; cdx[57] :=  0; cdx[58] :=  0; cdx[59] :=  0;
  3963.       cdx[60] :=  0;
  3964.       pdx[ 1] := -1; pdx[ 2] := -1; pdx[ 3] := -2; pdx[ 4] := -2;
  3965.       pdx[ 5] := -2; pdx[ 6] := -3; pdx[ 7] := -3; pdx[ 8] := -3;
  3966.       pdx[ 9] := -3; pdx[10] := -4; pdx[11] :=  0; pdx[12] := -2;
  3967.       pdx[13] := -1; pdx[14] :=  0; pdx[15] :=  0; pdx[16] :=  0;
  3968.       pdx[17] :=  0; pdx[18] :=  0; pdx[19] :=  0; pdx[20] :=  0;
  3969.       pdx[21] := -1; pdx[22] := -1; pdx[23] := -1;
  3970.     end;
  3971.  
  3972.   begin (*inittables*)
  3973.     reswords; symbols; rators;
  3974.     instrmnemonics; procmnemonics;
  3975.     chartypes; initdx;
  3976.   end (*inittables*) ;
  3977.  
  3978. begin
  3979.   (*initialize*)
  3980.   (************)
  3981.   initscalars; initsets; inittables;
  3982.  
  3983.  
  3984.   (*enter standard names and standard types:*)
  3985.   (******************************************)
  3986.   level := 0; top := 0;
  3987.   with display[0] do
  3988.     begin fname := nil; flabel := nil; occur := blck end;
  3989.   enterstdtypes;   stdnames; entstdnames;   enterundecl;
  3990.   top := 1; level := 1;
  3991.   with display[1] do
  3992.     begin fname := nil; flabel := nil; occur := blck end;
  3993.  
  3994.  
  3995.   (*compile:*) rewrite(prr); (*comment this out when compiling with pcom *)
  3996.   (**********)
  3997.   insymbol;
  3998.   programme(blockbegsys+statbegsys-[casesy]);
  3999.  
  4000. end.
  4001.